From patchwork Sun Mar 22 22:11:24 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 453245 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 7B87514007F for ; Mon, 23 Mar 2015 09:11:47 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass reason="1024-bit key; unprotected key" header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=qwREsfx1; dkim-adsp=none (unprotected policy); dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=iS+6OWfG+Ai5SEApH22i2hAbs2M+rQDUBEQhaB+e5QTSiBJCxCxio K4DTMdEGDhcrzIs+AttCKW29eTYY6d8okcHYkOv1qu7fiPVS3M8EAC+Y7kPlBggb 9Zr+feLK5WT69lgQUzgc3UwDAJGHVPUjsY5RAA7d0H1DbFGndeqrGo= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=ZAZut7ypD5BkvVSVgSZUk8ckxXw=; b=qwREsfx11nW4itpNfMNR kCrSbe7lKrmLoTZ/f8S5K9aQ53RY+1OW1R7I8JW9zm5rLKrExNh82bk8Nx385890 Qix5/TgFvR5/JmSEAtYUKq5th1fPdwufFknZn8ftF/ZDb48i3zrez5NNyG7ZRbUv u8tw+XL+d5KZJ5bFUsYZZbY= Received: (qmail 71501 invoked by alias); 22 Mar 2015 22:11:37 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 71388 invoked by uid 89); 22 Mar 2015 22:11:35 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=AWL, BAYES_50, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: nikam.ms.mff.cuni.cz Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sun, 22 Mar 2015 22:11:28 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id 289615441D6; Sun, 22 Mar 2015 23:11:24 +0100 (CET) Date: Sun, 22 Mar 2015 23:11:24 +0100 From: Jan Hubicka To: gcc-patches@gcc.gnu.org Subject: Fix ICEs on ODR violating programs and improve ODR mismatch diagnostic Message-ID: <20150322221123.GA26896@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Hi, this patch fixes ODR violation warnings on Chromium and firefox. I went through all of them and found two false positives. I also fixes two ICEs that are triggered by testcases martin found while delta reducing. I tested the patch on firefox,chromium and libreoffice. Martin gave it a try on boost and tried it with delta to reproduce more ICEs. The patch is bit bloated up by code reordering - I moved more readable checks to be before less readable and silenced duplicated warnings about a single type. There is still quite some new code in odr_subtypes_equivalent_p (which was sitting in my tree for a while) and I hope it is the last larger change I needed in this area. Otimally last fix for GCC 5 :) The false positives are the following: - The code in compare_virtual_tables had typo in skipping RTTI (when mixing -fno-rtti and -frtti code) and it also incorrectly assumed that all functions are DECL_VIRTUAL. This resulted in bogus warning about RTTI info mismatch on Chromium. - odr_subtypes_equivalent_p matched types by name that seems too restrictive. This resulted in mismatch on array "uint8_t a[8]". In one unit uint8_t was typedefed and in other #defined. Because unsigned char and uint8_t have the same mangling and othe properties, I do not think this counts as ODR violation. While evaulating errors I however found I can not tell what the bug is without actually looking into dumps, so I improve the diagnostics. warn_types_mismatch previously did nothing for types without TYPE_NAME that covers most of pointer, arrays and method types. I added code that actually compares them and is able to tell what subtype mismatch and why. Ohter common case was putting types in dfferent namespaces or by #define mismatch. I added code comparing manged names and output warnings: ../../third_party/zlib/zlib.h:1630:0: note: type name 'MOZ_Z_internal_state' should match type name 'internal_state' struct internal_state {int dummy;}; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/fx_zlib/zlib_v128/zlib.h:1811:0: note: the incompatible type is defined here struct internal_state {int dummy;}; ^ which hopefully makes it clear that someone got an idea to #define internal_state to MOZ_Z_internal_state and not be consistent. I also added code outputing sane diagnostic in case of component types and anonymous types. There are two anoying problems. First is that types are often output as struct instead of class and other is that location info tends to be wrong. For example in: gen/blink/core/CSSPropertyNames.cpp:2330:0: warning: type 'struct stringpool_t' violates one definition rule [-Wodr] static const short lookup[] = ^ gen/blink/core/CSSValueKeywords.cpp:4309:0: note: a different type is defined in another translation unit static const short lookup[] = ^ gen/blink/core/CSSPropertyNames.cpp:2330:0: note: the first difference of corresponding definitions is field 'stringpool_str0' static const short lookup[] = ^ gen/blink/core/CSSValueKeywords.cpp:4309:0: note: a field of same name but different type is defined in another translation unit static const short lookup[] = ^ This points after the actual definition to next statement. I will try to produce small testcase and work out where location gets garbled - it is wrong at FIELD_DECL itself that I do not tink can be mismerged by tree merging, so it seems a bug somewhere earlier. If location info would be correct there would be clear mismatch in the array bonds of stringpool_str0 array visible. For Chromium the errors output are now as follows. Comments are welcome (though I would like to avoid too many changes now). ../../third_party/ffmpeg/libavcodec/avcodec.h:1134:0: warning: type 'struct AVPacket' violates one definition rule [-Wodr] typedef struct AVPacket { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:1134:0: note: a different type is defined in another translation unit typedef struct AVPacket { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:1182:0: note: the first difference of corresponding definitions is field 'pos' int64_t pos; ///< byte position in stream, -1 if unknown ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:1178:0: note: a field with different name is defined in another translation unit void (*destruct)(struct AVPacket *); ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:1236:0: warning: type 'struct AVCodecContext' violates one definition rule [-Wodr] typedef struct AVCodecContext { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:1236:0: note: a different type is defined in another translation unit typedef struct AVCodecContext { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:2241:0: note: the first difference of corresponding definitions is field 'get_buffer2' int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:2129:0: note: a field with different name is defined in another translation unit int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic); ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3170:0: warning: type 'struct AVCodec' violates one definition rule [-Wodr] typedef struct AVCodec { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3170:0: note: a different type is defined in another translation unit typedef struct AVCodec { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3219:0: note: the first difference of corresponding definitions is field 'init_thread_copy' int (*init_thread_copy)(AVCodecContext *); ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3219:0: note: a field of same name but different type is defined in another translation unit int (*init_thread_copy)(AVCodecContext *); ^ lto1: note: type mismatch in parameter 1 ../../third_party/ffmpeg/libavcodec/avcodec.h:3138:0: note: type 'struct AVCodecContext' should match type 'struct AVCodecContext' that itself violate one definition rule } AVCodecContext; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3138:0: note: the incompatible type is defined here } AVCodecContext; ^ ../../third_party/ffmpeg/libavutil/frame.h:163:0: warning: type 'struct AVFrame' violates one definition rule [-Wodr] typedef struct AVFrame { ^ ../../third_party/ffmpeg/libavutil/frame.h:163:0: note: a different type is defined in another translation unit typedef struct AVFrame { ^ ../../third_party/ffmpeg/libavutil/frame.h:400:0: note: the first difference of corresponding definitions is field 'owner' struct AVCodecContext *owner; ^ ../../third_party/ffmpeg/libavutil/frame.h:400:0: note: a field of same name but different type is defined in another translation unit struct AVCodecContext *owner; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:1236:0: note: type 'struct AVCodecContext' should match type 'struct AVCodecContext' that itself violate one definition rule typedef struct AVCodecContext { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:1236:0: note: the incompatible type is defined here typedef struct AVCodecContext { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3272:0: warning: type 'struct AVHWAccel' violates one definition rule [-Wodr] typedef struct AVHWAccel { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3272:0: note: a different type is defined in another translation unit typedef struct AVHWAccel { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3319:0: note: the first difference of corresponding definitions is field 'alloc_frame' int (*alloc_frame)(AVCodecContext *avctx, AVFrame *frame); ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3319:0: note: a field of same name but different type is defined in another translation unit int (*alloc_frame)(AVCodecContext *avctx, AVFrame *frame); ^ lto1: note: type mismatch in parameter 1 ../../third_party/ffmpeg/libavcodec/avcodec.h:3138:0: note: type 'struct AVCodecContext' should match type 'struct AVCodecContext' that itself violate one definition rule } AVCodecContext; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3138:0: note: the incompatible type is defined here } AVCodecContext; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:4373:0: warning: type 'struct AVCodecParser' violates one definition rule [-Wodr] typedef struct AVCodecParser { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:4373:0: note: a different type is defined in another translation unit typedef struct AVCodecParser { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:4382:0: note: the first difference of corresponding definitions is field 'parser_parse' const uint8_t *buf, int buf_size); ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:4382:0: note: a field of same name but different type is defined in another translation unit const uint8_t *buf, int buf_size); ^ lto1: note: type mismatch in parameter 2 ../../third_party/ffmpeg/libavcodec/avcodec.h:3138:0: note: type 'struct AVCodecContext' should match type 'struct AVCodecContext' that itself violate one definition rule } AVCodecContext; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3138:0: note: the incompatible type is defined here } AVCodecContext; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:4217:0: warning: type 'struct AVCodecParserContext' violates one definition rule [-Wodr] typedef struct AVCodecParserContext { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:4371:0: note: a different type is defined in another translation unit } AVCodecParserContext; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:4219:0: note: the first difference of corresponding definitions is field 'parser' struct AVCodecParser *parser; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:4219:0: note: a field of same name but different type is defined in another translation unit struct AVCodecParser *parser; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:4373:0: note: type 'struct AVCodecParser' should match type 'struct AVCodecParser' that itself violate one definition rule typedef struct AVCodecParser { ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:4373:0: note: the incompatible type is defined here typedef struct AVCodecParser { ^ ../../third_party/ffmpeg/libavformat/avformat.h:1804:0: warning: type 'struct AVPacketList' violates one definition rule [-Wodr] typedef struct AVPacketList { ^ ../../third_party/ffmpeg/libavformat/avformat.h:1804:0: note: a different type is defined in another translation unit typedef struct AVPacketList { ^ ../../third_party/ffmpeg/libavformat/avformat.h:1805:0: note: the first difference of corresponding definitions is field 'pkt' AVPacket pkt; ^ ../../third_party/ffmpeg/libavformat/avformat.h:1805:0: note: a field of same name but different type is defined in another translation unit AVPacket pkt; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:1202:0: note: type 'struct AVPacket' should match type 'struct AVPacket' that itself violate one definition rule } AVPacket; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:1202:0: note: the incompatible type is defined here } AVPacket; ^ ../../third_party/ffmpeg/libavformat/avformat.h:783:0: warning: type 'struct AVStream' violates one definition rule [-Wodr] typedef struct AVStream { ^ ../../third_party/ffmpeg/libavformat/avformat.h:783:0: note: a different type is defined in another translation unit typedef struct AVStream { ^ ../../third_party/ffmpeg/libavformat/avformat.h:802:0: note: the first difference of corresponding definitions is field 'codec' AVCodecContext *codec; ^ ../../third_party/ffmpeg/libavformat/avformat.h:802:0: note: a field of same name but different type is defined in another translation unit AVCodecContext *codec; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3138:0: note: type 'struct AVCodecContext' should match type 'struct AVCodecContext' that itself violate one definition rule } AVCodecContext; ^ ../../third_party/ffmpeg/libavcodec/avcodec.h:3138:0: note: the incompatible type is defined here } AVCodecContext; ^ ../../third_party/ffmpeg/libavformat/avformat.h:1201:0: warning: type 'struct AVFormatContext' violates one definition rule [-Wodr] typedef struct AVFormatContext { ^ ../../third_party/ffmpeg/libavformat/avformat.h:1201:0: note: a different type is defined in another translation unit typedef struct AVFormatContext { ^ ../../third_party/ffmpeg/libavformat/avformat.h:1269:0: note: the first difference of corresponding definitions is field 'streams' AVStream **streams; ^ ../../third_party/ffmpeg/libavformat/avformat.h:1269:0: note: a field of same name but different type is defined in another translation unit AVStream **streams; ^ ../../third_party/ffmpeg/libavformat/avformat.h:1114:0: note: type 'struct AVStream' should match type 'struct AVStream' that itself violate one definition rule } AVStream; ^ ../../third_party/ffmpeg/libavformat/avformat.h:1114:0: note: the incompatible type is defined here } AVStream; ^ ../../third_party/ffmpeg/libavformat/avformat.h:564:0: warning: type 'struct AVInputFormat' violates one definition rule [-Wodr] typedef struct AVInputFormat { ^ ../../third_party/ffmpeg/libavformat/avformat.h:564:0: note: a different type is defined in another translation unit typedef struct AVInputFormat { ^ ../../third_party/ffmpeg/libavformat/avformat.h:634:0: note: the first difference of corresponding definitions is field 'read_header' int (*read_header)(struct AVFormatContext *); ^ ../../third_party/ffmpeg/libavformat/avformat.h:634:0: note: a field of same name but different type is defined in another translation unit int (*read_header)(struct AVFormatContext *); ^ lto1: note: type mismatch in parameter 1 ../../third_party/ffmpeg/libavformat/avformat.h:1201:0: note: type 'struct AVFormatContext' should match type 'struct AVFormatContext' that itself violate one definition rule typedef struct AVFormatContext { ^ ../../third_party/ffmpeg/libavformat/avformat.h:1201:0: note: the incompatible type is defined here typedef struct AVFormatContext { ^ ../../third_party/ffmpeg/libavformat/avformat.h:453:0: warning: type 'struct AVOutputFormat' violates one definition rule [-Wodr] typedef struct AVOutputFormat { ^ ../../third_party/ffmpeg/libavformat/avformat.h:453:0: note: a different type is defined in another translation unit typedef struct AVOutputFormat { ^ ../../third_party/ffmpeg/libavformat/avformat.h:497:0: note: the first difference of corresponding definitions is field 'write_header' int (*write_header)(struct AVFormatContext *); ^ ../../third_party/ffmpeg/libavformat/avformat.h:497:0: note: a field of same name but different type is defined in another translation unit int (*write_header)(struct AVFormatContext *); ^ lto1: note: type mismatch in parameter 1 ../../third_party/ffmpeg/libavformat/avformat.h:1201:0: note: type 'struct AVFormatContext' should match type 'struct AVFormatContext' that itself violate one definition rule typedef struct AVFormatContext { ^ ../../third_party/ffmpeg/libavformat/avformat.h:1201:0: note: the incompatible type is defined here typedef struct AVFormatContext { ^ gen/blink/core/CSSPropertyNames.cpp:2330:0: warning: type 'struct stringpool_t' violates one definition rule [-Wodr] static const short lookup[] = ^ gen/blink/core/CSSValueKeywords.cpp:4309:0: note: a different type is defined in another translation unit static const short lookup[] = ^ gen/blink/core/CSSPropertyNames.cpp:2330:0: note: the first difference of corresponding definitions is field 'stringpool_str0' static const short lookup[] = ^ gen/blink/core/CSSValueKeywords.cpp:4309:0: note: a field of same name but different type is defined in another translation unit static const short lookup[] = ^ lto1: note: array types have different bounds gen/blink/core/XPathGrammar.h:66:0: warning: type 'union YYSTYPE' violates one definition rule [-Wodr] typedef union YYSTYPE ^ ../../../../out/Release/gen/blink/core/CSSGrammar.cpp:274:0: note: a different type is defined in another translation unit xml/XPathGrammar.y:59:0: note: the first difference of corresponding definitions is field 'axis' css/parser/CSSGrammar.y:70:0: note: a field with different name is defined in another translation unit ../../../../out/Release/gen/blink/core/CSSGrammar.cpp:541:0: warning: type 'union yyalloc' violates one definition rule [-Wodr] ../../../../out/Release/gen/blink/core/XPathGrammar.cpp:226:0: note: a different type is defined in another translation unit ../../../../out/Release/gen/blink/core/CSSGrammar.cpp:541:0: note: the first difference of corresponding definitions is field 'yyvs_alloc' ../../../../out/Release/gen/blink/core/XPathGrammar.cpp:226:0: note: a field of same name but different type is defined in another translation unit ../../../../out/Release/gen/blink/core/CSSGrammar.cpp:313:0: note: type 'union YYSTYPE' should match type 'union YYSTYPE' that itself violate one definition rule ../../../../out/Release/gen/blink/core/XPathGrammar.cpp:177:0: note: the incompatible type is defined here ../../third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h:295:0: warning: type 'struct WebCryptoEcKeyImportParams' violates one definition rule [-Wodr] class WebCryptoEcKeyImportParams : public WebCryptoAlgorithmParams { ^ ../../third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h:295:0: note: a different type is defined in another translation unit class WebCryptoEcKeyImportParams : public WebCryptoAlgorithmParams { ^ ../../third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h:307:0: note: the first difference of corresponding definitions is field 'm_namedCurve' const WebCryptoNamedCurve m_namedCurve; ^ ../../third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h:295:0: note: a field of same name but different type is defined in another translation unit class WebCryptoEcKeyImportParams : public WebCryptoAlgorithmParams { ^ ../../third_party/WebKit/public/platform/WebCryptoAlgorithm.h:80:0: note: type 'const WebCryptoNamedCurve' should match type 'const WebCryptoNamedCurve' enum WebCryptoNamedCurve { ^ ../../third_party/WebKit/public/platform/WebCryptoAlgorithm.h:81:0: note: the incompatible type is defined here WebCryptoNamedCurveP256, ^ ../../third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h:61:0: warning: type 'struct ObserveEvent' violates one definition rule [-Wodr] typedef void (Observer::*ObserveEvent)(bool, Key, Data); ^ ../../third_party/libaddressinput/src/cpp/include/libaddressinput/callback.h:59:0: note: a different type is defined in another translation unit class CallbackImpl : public Callback { ^ ../../third_party/libaddressinput/src/cpp/src/retriever.cc:96:0: note: the first difference of corresponding definitions is field '__pfn' const scoped_ptr validated_data_ready_; ^ ../../third_party/libaddressinput/src/cpp/src/validating_storage.cc:43:0: note: a field of same name but different type is defined in another translation unit wrapped_data_ready_(BuildCallback(this, &Helper::OnWrappedDataReady)) { ^ lto1: note: type mismatch in parameter 1 ../../third_party/libaddressinput/src/cpp/src/retriever.cc:96:0: note: type 'struct Helper' defined in anonymous namespace can not match type 'struct Helper' const scoped_ptr validated_data_ready_; ^ ../../third_party/libaddressinput/src/cpp/src/validating_storage.cc:37:0: note: the incompatible type defined in anonymous namespace in another translation unit class Helper { ^ /usr/include/freetype2/freetype/ftimage.h:310:0: warning: type 'struct FT_Bitmap_' violates one definition rule [-Wodr] typedef struct FT_Bitmap_ ^ ../../third_party/pdfium/third_party/freetype/include/ftimage.h:75:0: note: a different type is defined in another translation unit { ^ /usr/include/freetype2/freetype/ftimage.h:312:0: note: the first difference of corresponding definitions is field 'rows' int rows; ^ ../../third_party/pdfium/third_party/freetype/include/ftimage.h:75:0: note: a field of same name but different type is defined in another translation unit { ^ lto1: note: type 'int' should match type 'unsigned int' /usr/include/freetype2/freetype/freetype.h:1605:0: warning: type 'struct FT_GlyphSlotRec_' violates one definition rule [-Wodr] typedef struct FT_GlyphSlotRec_ ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: a different type is defined in another translation unit typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ /usr/include/freetype2/freetype/freetype.h:1620:0: note: the first difference of corresponding definitions is field 'bitmap' FT_Bitmap bitmap; ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: a field of same name but different type is defined in another translation unit typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ /usr/include/freetype2/freetype/ftimage.h:321:0: note: type 'struct FT_Bitmap' should match type 'struct FT_Bitmap' that itself violate one definition rule } FT_Bitmap; ^ ../../third_party/pdfium/third_party/freetype/include/ftimage.h:75:0: note: the incompatible type is defined here { ^ /usr/include/freetype2/freetype/freetype.h:912:0: warning: type 'struct FT_FaceRec_' violates one definition rule [-Wodr] typedef struct FT_FaceRec_ ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: a different type is defined in another translation unit typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ /usr/include/freetype2/freetype/freetype.h:949:0: note: the first difference of corresponding definitions is field 'glyph' FT_GlyphSlot glyph; ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: a field of same name but different type is defined in another translation unit typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ /usr/include/freetype2/freetype/freetype.h:450:0: note: type 'struct FT_GlyphSlotRec_ *' should match type 'struct FT_GlyphSlotRec_ *' typedef struct FT_GlyphSlotRec_* FT_GlyphSlot; ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: the incompatible type is defined here typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ /usr/include/freetype2/freetype/freetype.h:736:0: warning: type 'struct FT_CharMapRec_' violates one definition rule [-Wodr] typedef struct FT_CharMapRec_ ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: a different type is defined in another translation unit typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ /usr/include/freetype2/freetype/freetype.h:738:0: note: the first difference of corresponding definitions is field 'face' FT_Face face; ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: a field of same name but different type is defined in another translation unit typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ /usr/include/freetype2/freetype/freetype.h:399:0: note: type 'struct FT_FaceRec_ *' should match type 'struct FT_FaceRec_ *' typedef struct FT_FaceRec_* FT_Face; ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: the incompatible type is defined here typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ /usr/include/freetype2/freetype/freetype.h:1395:0: warning: type 'struct FT_SizeRec_' violates one definition rule [-Wodr] typedef struct FT_SizeRec_ ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: a different type is defined in another translation unit typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ /usr/include/freetype2/freetype/freetype.h:1397:0: note: the first difference of corresponding definitions is field 'face' FT_Face face; /* parent face object */ ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: a field of same name but different type is defined in another translation unit typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ /usr/include/freetype2/freetype/freetype.h:399:0: note: type 'struct FT_FaceRec_ *' should match type 'struct FT_FaceRec_ *' typedef struct FT_FaceRec_* FT_Face; ^ ../../third_party/pdfium/third_party/freetype/include/freetype.h:847:0: note: the incompatible type is defined here typedef struct FT_Face_InternalRec_* FT_Face_Internal; ^ ../../third_party/zlib/zlib.h:85:16: warning: type 'struct z_stream_s' violates one definition rule [-Wodr] typedef struct z_stream_s { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/fx_zlib/zlib_v128/zlib.h:1811:0: note: a different type is defined in another translation unit struct internal_state {int dummy;}; ^ ../../third_party/zlib/zlib.h:95:32: note: the first difference of corresponding definitions is field 'state' struct internal_state FAR *state; /* not visible by applications */ ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/fx_zlib/zlib_v128/zlib.h:1811:0: note: a field of same name but different type is defined in another translation unit struct internal_state {int dummy;}; ^ ../../third_party/zlib/zlib.h:1630:0: note: type name 'MOZ_Z_internal_state' should match type name 'internal_state' struct internal_state {int dummy;}; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/fx_zlib/zlib_v128/zlib.h:1811:0: note: the incompatible type is defined here struct internal_state {int dummy;}; ^ ../../third_party/libjpeg_turbo/jpeglib.h:286:0: warning: type 'struct jpeg_common_struct' violates one definition rule [-Wodr] struct jpeg_common_struct { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: a different type is defined in another translation unit jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:287:0: note: the first difference of corresponding definitions is field 'is_decompressor' jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: a field of same name but different type is defined in another translation unit jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/libjpeg_turbo/jmorecfg.h:238:0: note: type 'boolean' should match type 'boolean' typedef int boolean; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jconfig.h:26:0: note: the incompatible type is defined here typedef unsigned char boolean; ^ ../../third_party/libjpeg_turbo/jpeglib.h:724:0: warning: type 'struct jpeg_error_mgr' violates one definition rule [-Wodr] struct jpeg_error_mgr { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: a different type is defined in another translation unit jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:726:0: note: the first difference of corresponding definitions is field 'error_exit' JMETHOD(void, error_exit, (j_common_ptr cinfo)); ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: a field of same name but different type is defined in another translation unit jpeg_common_fields; /* Fields common to both master struct types */ ^ lto1: note: type mismatch in parameter 1 ../../third_party/libjpeg_turbo/jpeglib.h:294:0: note: type 'struct jpeg_common_struct *' should match type 'struct jpeg_common_struct *' typedef struct jpeg_common_struct * j_common_ptr; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: the incompatible type is defined here jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:837:0: warning: type 'struct jpeg_memory_mgr' violates one definition rule [-Wodr] struct jpeg_memory_mgr { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: a different type is defined in another translation unit jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:839:0: note: the first difference of corresponding definitions is field 'alloc_small' JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: a field of same name but different type is defined in another translation unit jpeg_common_fields; /* Fields common to both master struct types */ ^ lto1: note: type mismatch in parameter 1 ../../third_party/libjpeg_turbo/jpeglib.h:294:0: note: type 'struct jpeg_common_struct *' should match type 'struct jpeg_common_struct *' typedef struct jpeg_common_struct * j_common_ptr; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: the incompatible type is defined here jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:782:0: warning: type 'struct jpeg_progress_mgr' violates one definition rule [-Wodr] struct jpeg_progress_mgr { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: a different type is defined in another translation unit jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:783:0: note: the first difference of corresponding definitions is field 'progress_monitor' JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: a field of same name but different type is defined in another translation unit jpeg_common_fields; /* Fields common to both master struct types */ ^ lto1: note: type mismatch in parameter 1 ../../third_party/libjpeg_turbo/jpeglib.h:294:0: note: type 'struct jpeg_common_struct *' should match type 'struct jpeg_common_struct *' typedef struct jpeg_common_struct * j_common_ptr; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: the incompatible type is defined here jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:102:0: warning: type 'struct JQUANT_TBL' violates one definition rule [-Wodr] } JQUANT_TBL; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:150:0: note: a different type is defined in another translation unit typedef struct { ^ ../../third_party/libjpeg_turbo/jpeglib.h:101:0: note: the first difference of corresponding definitions is field 'sent_table' boolean sent_table; /* TRUE when table has been output */ ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:150:0: note: a field of same name but different type is defined in another translation unit typedef struct { ^ ../../third_party/libjpeg_turbo/jmorecfg.h:238:0: note: type 'boolean' should match type 'boolean' typedef int boolean; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jconfig.h:26:0: note: the incompatible type is defined here typedef unsigned char boolean; ^ ../../third_party/libjpeg_turbo/jpeglib.h:118:0: warning: type 'struct JHUFF_TBL' violates one definition rule [-Wodr] } JHUFF_TBL; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:169:0: note: a different type is defined in another translation unit UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:117:0: note: the first difference of corresponding definitions is field 'sent_table' boolean sent_table; /* TRUE when table has been output */ ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:169:0: note: a field of same name but different type is defined in another translation unit UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ ^ ../../third_party/libjpeg_turbo/jmorecfg.h:238:0: note: type 'boolean' should match type 'boolean' typedef int boolean; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jconfig.h:26:0: note: the incompatible type is defined here typedef unsigned char boolean; ^ ../../third_party/libjpeg_turbo/jpeglib.h:191:0: warning: type 'struct jpeg_component_info' violates one definition rule [-Wodr] } jpeg_component_info; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:169:0: note: a different type is defined in another translation unit UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:172:0: note: the first difference of corresponding definitions is field 'component_needed' boolean component_needed; /* do we need the value of this component? */ ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:169:0: note: a field of same name but different type is defined in another translation unit UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ ^ ../../third_party/libjpeg_turbo/jmorecfg.h:238:0: note: type 'boolean' should match type 'boolean' typedef int boolean; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jconfig.h:26:0: note: the incompatible type is defined here typedef unsigned char boolean; ^ ../../third_party/libjpeg_turbo/jpeglib.h:476:0: warning: type 'struct jpeg_decompress_struct' violates one definition rule [-Wodr] struct jpeg_decompress_struct { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:169:0: note: a different type is defined in another translation unit UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:477:0: note: the first difference of corresponding definitions is field 'err' jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:169:0: note: a field of same name but different type is defined in another translation unit UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:724:0: note: type 'struct jpeg_error_mgr' should match type 'struct jpeg_error_mgr' that itself violate one definition rule struct jpeg_error_mgr { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: the incompatible type is defined here jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:806:0: warning: type 'struct jpeg_source_mgr' violates one definition rule [-Wodr] struct jpeg_source_mgr { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:169:0: note: a different type is defined in another translation unit UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:810:0: note: the first difference of corresponding definitions is field 'init_source' JMETHOD(void, init_source, (j_decompress_ptr cinfo)); ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:169:0: note: a field of same name but different type is defined in another translation unit UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ ^ lto1: note: type mismatch in parameter 1 ../../third_party/libjpeg_turbo/jpeglib.h:296:0: note: type 'struct jpeg_decompress_struct *' should match type 'struct jpeg_decompress_struct *' typedef struct jpeg_decompress_struct * j_decompress_ptr; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:169:0: note: the incompatible type is defined here UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:301:0: warning: type 'struct jpeg_compress_struct' violates one definition rule [-Wodr] struct jpeg_compress_struct { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:251:0: note: a different type is defined in another translation unit typedef struct { ^ ../../third_party/libjpeg_turbo/jpeglib.h:302:0: note: the first difference of corresponding definitions is field 'err' jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:251:0: note: a field of same name but different type is defined in another translation unit typedef struct { ^ ../../third_party/libjpeg_turbo/jpeglib.h:724:0: note: type 'struct jpeg_error_mgr' should match type 'struct jpeg_error_mgr' that itself violate one definition rule struct jpeg_error_mgr { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:321:0: note: the incompatible type is defined here jpeg_common_fields; /* Fields common to both master struct types */ ^ ../../third_party/libjpeg_turbo/jpeglib.h:794:0: warning: type 'struct jpeg_destination_mgr' violates one definition rule [-Wodr] struct jpeg_destination_mgr { ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:251:0: note: a different type is defined in another translation unit typedef struct { ^ ../../third_party/libjpeg_turbo/jpeglib.h:798:0: note: the first difference of corresponding definitions is field 'init_destination' JMETHOD(void, init_destination, (j_compress_ptr cinfo)); ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:251:0: note: a field of same name but different type is defined in another translation unit typedef struct { ^ lto1: note: type mismatch in parameter 1 ../../third_party/libjpeg_turbo/jpeglib.h:295:0: note: type 'struct jpeg_compress_struct *' should match type 'struct jpeg_compress_struct *' typedef struct jpeg_compress_struct * j_compress_ptr; ^ ../../third_party/pdfium/core/src/fxcodec/codec/../.././fxcodec/libjpeg/jpeglib.h:251:0: note: the incompatible type is defined here typedef struct { ^ ../../third_party/pdfium/fpdfsdk/src/javascript/../../include/javascript/event.h:41:0: warning: type 'struct event' violates one definition rule [-Wodr] { ^ ../../third_party/libevent/event.h:213:0: note: a type with different bases is defined in another translation unit struct event { ^ ./glslang_lex.cpp:968:0: warning: type 'struct yyguts_t' violates one definition rule [-Wodr] ./Tokenizer.cpp:348:0: note: a different type is defined in another translation unit ./glslang_lex.cpp:968:0: note: the first difference of corresponding definitions is field 'yyextra_r' ./Tokenizer.cpp:348:0: note: a field of same name but different type is defined in another translation unit ../../third_party/angle/src/compiler/translator/ParseContext.h:52:0: note: type name 'TParseContext' should match type name 'pp::Tokenizer::Context' int shaderVersion; ^ ../../third_party/angle/src/compiler/preprocessor/Tokenizer.h:23:0: note: the incompatible type is defined here { ^ /usr/include/linux/if.h:210:0: warning: type 'union ' violates one definition rule [-Wodr] union { ^ /usr/include/net/if.h:133:0: note: a different type is defined in another translation unit char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ ^ /usr/include/linux/if.h:222:0: note: the first difference of corresponding definitions is field 'ifru_data' void * ifru_data; ^ /usr/include/net/if.h:133:0: note: a field of same name but different type is defined in another translation unit char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ ^ lto1: note: type 'void' should match type 'char' /usr/include/linux/if.h:203:0: warning: type 'struct ifreq' violates one definition rule [-Wodr] struct ifreq { ^ /usr/include/net/if.h:133:0: note: a different type is defined in another translation unit char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ ^ /usr/include/linux/if.h:224:0: note: the first difference of corresponding definitions is field 'ifr_ifru' } ifr_ifru; ^ /usr/include/net/if.h:133:0: note: a field of same name but different type is defined in another translation unit char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ ^ /usr/include/linux/if.h:210:0: note: type 'union ' should match type 'union ' that itself violate one definition rule union { ^ /usr/include/net/if.h:133:0: note: the incompatible type is defined here char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ ^ Bootstrapped/regtested x86_64-linux, will commit it later today. Honza PR ipa/65475 * g++.dg/lto/pr65475b_0.C: New testcase. * g++.dg/lto/pr65475b_1.C: New testcase. * g++.dg/lto/pr65475c_0.C: New testcase. * g++.dg/lto/pr65475c_1.C: New testcase. * ipa-devirt.c: Include demangle.h (odr_type_d): Add field rtti_broken. (odr_subtypes_equivalent_p): Do not require name to match. (compare_virtual_tables): Fix typo; if type already has ODR violation, bypass the tests; be ready for function referneces in vtables that are not DECL_VIRTUAL; make warnings to be OPT_Wodr. (warn_odr): Give up for nameless types. (warn_types_mismatch): Report mismatch in mangled names; report mismatch in anonymous namespaces; look into component types to give useful error; report when mismatch is dragged in from other ODR type. (odr_types_equivalent_p): Match types for being polymorphic; avoid duplicated diagnostics. (add_type_duplicate): Reorder checks so more informative ones come first; fix typo; do not output "the extra base is defined here" when we did not warn. (BINFO_N_BASE_BINFOS): Relax sanity check. Index: testsuite/g++.dg/lto/pr65475c_1.C =================================================================== --- testsuite/g++.dg/lto/pr65475c_1.C (revision 0) +++ testsuite/g++.dg/lto/pr65475c_1.C (revision 0) @@ -0,0 +1,234 @@ +namespace std +{ + template < class _CharT > struct char_traits; + typedef long streamsize; + template < typename _CharT, typename _Traits = + char_traits < _CharT > >class basic_ostream; + template < typename _CharT, typename _Traits = + char_traits < _CharT > >class Trans_NS___cxx11_basic_ostringstream; + template < typename _CharT, typename _Traits = + char_traits < _CharT > >class istreambuf_iterator; + template < typename _CharT, typename _Traits = + char_traits < _CharT > >class ostreambuf_iterator; +} +namespace std +{ + template < typename _CharT, typename _InIter = + istreambuf_iterator < _CharT > >class num_get; + template < typename _CharT, typename _OutIter = + ostreambuf_iterator < _CharT > >class num_put; + struct iterator + { + }; +} +typedef int _Atomic_word; +namespace std +{ + class locale + { + public:class facet; + class _Impl; + template < typename _Facet > locale ( const locale & __other, + _Facet * __f ); + private: _Impl * _M_impl; + }; + class locale::facet + { + mutable _Atomic_word _M_refcount; + protected: explicit facet ( void ) throw ( ); + virtual ~ facet ( ); + }; + enum _Ios_Fmtflags + { + _S_boolalpha = 1 << 0, _S_dec, _S_fixed = 1 << 2, _S_hex = + 1 << 3, _S_internal = 1 << 4, _S_left = 1 << 5, _S_oct = + 1 << 6, _S_right = 1 << 7, _S_scientific = 1 << 8, _S_showbase = + 1 << 9, _S_showpoint = 1 << 10, _S_showpos = 1 << 11, _S_skipws = + 1 << 12, _S_unitbuf = 1 << 13, _S_uppercase = 1 << 14, _S_adjustfield = + _S_left | _S_right | _S_internal, _S_basefield = + _S_dec | _S_oct | _S_hex, _S_floatfield = + _S_scientific | _S_fixed, _S_ios_fmtflags_end = 1 << 16 + }; + enum _Ios_Openmode + { + _S_out + }; + enum _Ios_Iostate + { + _S_goodbit, _S_badbit, _S_eofbit, _S_failbit = + 1 << 2, _S_ios_iostate_end = 1 << 16 + }; + class ios_base + { + public:typedef _Ios_Fmtflags fmtflags; + typedef _Ios_Iostate iostate; + protected: streamsize _M_precision; + streamsize _M_width; + fmtflags _M_flags; + iostate _M_exception; + iostate _M_streambuf_state; + struct _Callback_list; + _Callback_list *_M_callbacks; + struct _Words + { + void *_M_pword; + long _M_iword; + }; + _Words _M_word_zero; + enum + { + _S_local_word_size = 8 + }; + _Words _M_local_word[_S_local_word_size]; + int _M_word_size; + _Words *_M_word; + locale _M_ios_locale; + virtual ~ ios_base ( ); + }; + template < typename _CharT, typename _Traits > class basic_streambuf; +template < typename _CharT, typename _Traits > class ostreambuf_iterator:public + iterator + { + typedef basic_ostream < wchar_t, _Traits > ostream_type; + }; + class __ctype_abstract_base:public locale::facet + { + }; +template < typename _CharT > class ctype:public __ctype_abstract_base + { + }; + class Trans_NS___cxx11_numpunct:public locale::facet + { + }; +template < typename _CharT, typename _InIter > class num_get:public locale:: + facet + { + }; +template < typename _CharT, typename _OutIter > class num_put:public locale:: + facet + { + public:typedef int char_type; + typedef std::ostreambuf_iterator < wchar_t, + std::char_traits < wchar_t > >iter_type; + }; +template < typename _CharT, typename _Traits > class basic_ios:public + ios_base + { + public:typedef wchar_t char_type; + typedef num_get < wchar_t, istreambuf_iterator < wchar_t, + _Traits > >__num_get_type; + protected:basic_ostream < wchar_t, _Traits > *_M_tie; + mutable char_type _M_fill; + mutable bool _M_fill_init; + basic_streambuf < wchar_t, _Traits > *_M_streambuf; + const ctype < wchar_t > *_M_ctype; + const num_put < wchar_t, ostreambuf_iterator < wchar_t, + _Traits > >*_M_num_put; + const __num_get_type *_M_num_get; + }; +template < typename _CharT, typename _Traits > class basic_ostream:virtual public basic_ios < wchar_t, + _Traits + > + { + }; +} +typedef enum +{ + posix +} +value_type; +static const unsigned int wchar_t_facet = 1 << 1; +class shared_ptr +{ +}; +namespace std +{ +template < typename _CharT, typename _Traits > class Trans_NS___cxx11_basic_ostringstream:public basic_ostream < wchar_t, + _Traits + > + { + public:explicit Trans_NS___cxx11_basic_ostringstream ( void ); + }; +} +class base_num_format:public + std::num_put < + wchar_t > +{ +public:typedef typename + std::num_put < + wchar_t >::iter_type + iter_type; + typedef wchar_t + char_type; + base_num_format ( unsigned long refs = 0 ); + iter_type + do_put_out; + std::ios_base & + do_put_ios; + char_type + do_put_fill; + unsigned long long + do_put_val; + virtual iter_type + do_put ( void ) const + { + return + do_real_put ( do_put_out, do_put_ios, do_put_fill, do_put_val ); + } +private:template < + typename + ValueType > + iter_type + do_real_put ( iter_type out, std::ios_base & ios, char_type fill, + ValueType val ) const + { + switch ( 0 ) + case posix: + { + typedef + std::Trans_NS___cxx11_basic_ostringstream < + char_type > + sstream_type; + sstream_type + ss; + } + } +}; +class + base_num_parse: + public + std::num_get < + wchar_t > +{ +private:}; +class + num_format: + public + base_num_format +{ +public:typedef wchar_t + iter_type; + num_format ( shared_ptr lc, unsigned long refs = 0 ) + { + } +}; +class + num_punct_posix: + public + std::Trans_NS___cxx11_numpunct +{ +}; +template < typename CharType > + std::locale create_formatting_impl ( std::locale const &in, shared_ptr lc ) +{ + std::locale tmp = std::locale ( tmp, new num_format ( lc ) ); +} +shared_ptr create_formatting_lc; +unsigned int create_formatting_type; +void +create_formatting ( std::locale const &in ) +{ + switch ( create_formatting_type ) + case wchar_t_facet: + create_formatting_impl < wchar_t > ( in, create_formatting_lc ); +} Index: testsuite/g++.dg/lto/pr65475b_0.C =================================================================== --- testsuite/g++.dg/lto/pr65475b_0.C (revision 0) +++ testsuite/g++.dg/lto/pr65475b_0.C (revision 0) @@ -0,0 +1,9 @@ +/* { dg-lto-do link } */ +/* { dg-options "-O2 -Wno-odr" } */ +/* { dg-extra-ld-options { -O2 -Wno-odr -r -nostdlib } } */ +namespace std { +class exception {}; +class runtime_error : exception { + virtual char m_fn1(); +} a; +} Index: testsuite/g++.dg/lto/pr65475b_1.C =================================================================== --- testsuite/g++.dg/lto/pr65475b_1.C (revision 0) +++ testsuite/g++.dg/lto/pr65475b_1.C (revision 0) @@ -0,0 +1,7 @@ +namespace std { +class exception { + virtual char m_fn1(); +}; +class runtime_error : exception { +} b; +} Index: testsuite/g++.dg/lto/pr65475c_0.C =================================================================== --- testsuite/g++.dg/lto/pr65475c_0.C (revision 0) +++ testsuite/g++.dg/lto/pr65475c_0.C (revision 0) @@ -0,0 +1,156 @@ +/* { dg-lto-do link } */ +/* { dg-lto-options "-O2 -w" } */ +/* { dg-extra-ld-options { -O2 -Wno-odr -r -nostdlib } } */ +namespace std +{ +template < class > struct char_traits; +typedef long streamsize; +template < typename, typename > class basic_streambuf; +template < typename > class A; +template < typename, typename > class basic_ostream; +template < typename _CharT, typename = + char_traits < _CharT > >class istreambuf_iterator; +template < typename _CharT, typename = + char_traits < _CharT > >class ostreambuf_iterator; +template < typename > class ctype; +template < typename _CharT, typename = + istreambuf_iterator < _CharT > >class num_get; +template < typename _CharT, typename = + ostreambuf_iterator < _CharT > >class num_put; +} +typedef int _Atomic_word; +namespace std +{ +class locale +{ + class facet; + class _Impl; + _Impl *_M_impl; +}; +class locale::facet +{ + _Atomic_word _M_refcount; +protected: + virtual ~ facet (); +}; +enum _Ios_Fmtflags +{ _S_boolalpha = 1, _S_dec, _S_fixed = 1 << 2, _S_hex = + 1 << 3, _S_internal = 1 << 4, _S_left = 1 << 5, _S_oct = + 1 << 6, _S_right = 1 << 7, _S_scientific = 1 << 8, _S_showbase = + 1 << 9, _S_showpoint = 1 << 10, _S_showpos = 1 << 11, _S_skipws = + 1 << 12, _S_unitbuf = 1 << 13, _S_uppercase = 1 << 14, _S_adjustfield = + _S_left | _S_right | _S_internal, _S_basefield = + _S_dec | _S_oct | _S_hex, _S_floatfield = + _S_scientific | _S_fixed, _S_ios_fmtflags_end = 1 << 16 +}; +enum _Ios_Iostate +{ _S_goodbit, _S_badbit, _S_eofbit, _S_failbit = + 1 << 2, _S_ios_iostate_end = 1 << 16 +}; +class ios_base +{ + typedef _Ios_Fmtflags fmtflags; + typedef _Ios_Iostate iostate; + streamsize _M_precision; + streamsize _M_width; + fmtflags _M_flags; + iostate _M_exception; + iostate _M_streambuf_state; + struct _Callback_list; + _Callback_list *_M_callbacks; + struct _Words + { + void *_M_pword; + long _M_iword; + } _M_word_zero; + enum + { _S_local_word_size = 8 }; + _Words _M_local_word[_S_local_word_size]; + int _M_word_size; + _Words *_M_word; + locale _M_ios_locale; + virtual ~ ios_base (); +}; +template < typename, typename > class istreambuf_iterator +{ + typedef A < char_traits < wchar_t > >istream_type; +}; +template < typename, typename > class ostreambuf_iterator +{ + typedef basic_ostream < wchar_t, char_traits < wchar_t > >ostream_type; +}; +template < typename, typename > class num_get:locale::facet +{ +public: + typedef istreambuf_iterator < wchar_t > iter_type; +}; +template < typename, typename > class num_put:locale::facet +{ +public: + typedef ostreambuf_iterator < wchar_t > iter_type; +}; +template < typename, typename > class basic_ios:ios_base +{ + typedef wchar_t char_type; + basic_ostream < wchar_t, char_traits < wchar_t > >*_M_tie; + char_type _M_fill; + bool _M_fill_init; + basic_streambuf < wchar_t, char_traits < wchar_t > >*_M_streambuf; + ctype < wchar_t > *_M_ctype; + num_put < wchar_t > *_M_num_put; + num_get < wchar_t > *_M_num_get; +}; +template < typename, typename > class basic_ostream:virtual basic_ios < wchar_t, + char_traits < wchar_t > + > +{ + typedef basic_ios __ios_type; +}; +template < typename > class A:basic_ios < wchar_t, int > +{ +}; +class B:A < char_traits < wchar_t > >, basic_ostream < wchar_t, + char_traits < wchar_t > > +{ +}; +} + +class C: + std::num_put < + wchar_t > +{ +public: + C (int); + iter_type + do_put_out; +}; +class + D: + std::num_get < + wchar_t > +{ +public: + D (int); + iter_type + do_get_in; +}; +template < typename > void +install_formatting_facets (std::locale, int p2) +{ + (C (p2)); +} + +template < typename > void +install_parsing_facets (std::locale, int p2) +{ + (D (p2)); +} + +std::locale a; +int b; +void +create_formatting () +{ + install_formatting_facets < wchar_t > (a, b); + install_parsing_facets < wchar_t > (a, b); +} Index: ipa-devirt.c =================================================================== --- ipa-devirt.c (revision 221572) +++ ipa-devirt.c (working copy) @@ -166,6 +166,7 @@ along with GCC; see the file COPYING3. #include "gimple-pretty-print.h" #include "stor-layout.h" #include "intl.h" +#include "demangle.h" /* Hash based set of pairs of types. */ typedef struct @@ -239,6 +240,8 @@ struct GTY(()) odr_type_d bool all_derivations_known; /* Did we report ODR violation here? */ bool odr_violated; + /* Set when virtual table without RTTI previaled table with. */ + bool rtti_broken; }; /* Return TRUE if all derived types of T are known and thus @@ -673,8 +676,6 @@ odr_subtypes_equivalent_p (tree t1, tree return false; if ((TYPE_NAME (t1) == NULL_TREE) != (TYPE_NAME (t2) == NULL_TREE)) return false; - if (TYPE_NAME (t1) && DECL_NAME (TYPE_NAME (t1)) != DECL_NAME (TYPE_NAME (t2))) - return false; type_pair pair={t1,t2}; if (TYPE_UID (t1) > TYPE_UID (t2)) @@ -694,6 +695,7 @@ void compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable) { int n1, n2; + if (DECL_VIRTUAL_P (prevailing->decl) != DECL_VIRTUAL_P (vtable->decl)) { odr_violation_reported = true; @@ -715,6 +717,17 @@ compare_virtual_tables (varpool_node *pr } if (!prevailing->definition || !vtable->definition) return; + + /* If we do not stream ODR type info, do not bother to do useful compare. */ + if (!TYPE_BINFO (DECL_CONTEXT (vtable->decl)) + || !polymorphic_type_binfo_p (TYPE_BINFO (DECL_CONTEXT (vtable->decl)))) + return; + + odr_type class_type = get_odr_type (DECL_CONTEXT (vtable->decl), true); + + if (class_type->odr_violated) + return; + for (n1 = 0, n2 = 0; true; n1++, n2++) { struct ipa_ref *ref1, *ref2; @@ -730,13 +743,16 @@ compare_virtual_tables (varpool_node *pr && (end1 || (DECL_ASSEMBLER_NAME (ref1->referred->decl) != DECL_ASSEMBLER_NAME (ref2->referred->decl) - && DECL_VIRTUAL_P (ref1->referred->decl))) - && !DECL_VIRTUAL_P (ref2->referred->decl)) + && TREE_CODE (ref1->referred->decl) == FUNCTION_DECL)) + && TREE_CODE (ref2->referred->decl) != FUNCTION_DECL) { - if (warning_at (DECL_SOURCE_LOCATION - (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0, - "virtual table of type %qD contains RTTI information", - DECL_CONTEXT (vtable->decl))) + if (!class_type->rtti_broken + && warning_at (DECL_SOURCE_LOCATION + (TYPE_NAME (DECL_CONTEXT (vtable->decl))), + OPT_Wodr, + "virtual table of type %qD contains RTTI " + "information", + DECL_CONTEXT (vtable->decl))) { inform (DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (prevailing->decl))), @@ -745,6 +761,7 @@ compare_virtual_tables (varpool_node *pr inform (DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (prevailing->decl))), "RTTI will not work on this type"); + class_type->rtti_broken = true; } n2++; end2 = !vtable->iterate_reference (n2, ref2); @@ -753,11 +770,11 @@ compare_virtual_tables (varpool_node *pr && (end2 || (DECL_ASSEMBLER_NAME (ref2->referred->decl) != DECL_ASSEMBLER_NAME (ref1->referred->decl) - && DECL_VIRTUAL_P (ref2->referred->decl))) - && !DECL_VIRTUAL_P (ref1->referred->decl)) + && TREE_CODE (ref2->referred->decl) == FUNCTION_DECL)) + && TREE_CODE (ref1->referred->decl) != FUNCTION_DECL) { n1++; - end1 = !vtable->iterate_reference (n1, ref1); + end1 = !prevailing->iterate_reference (n1, ref1); } /* Finished? */ @@ -770,8 +787,10 @@ compare_virtual_tables (varpool_node *pr is not output too often. */ if (DECL_SIZE (prevailing->decl) != DECL_SIZE (vtable->decl)) { + class_type->odr_violated = true; if (warning_at (DECL_SOURCE_LOCATION - (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0, + (TYPE_NAME (DECL_CONTEXT (vtable->decl))), + OPT_Wodr, "virtual table of type %qD violates " "one definition rule ", DECL_CONTEXT (vtable->decl))) @@ -791,13 +810,16 @@ compare_virtual_tables (varpool_node *pr == DECL_ASSEMBLER_NAME (ref2->referred->decl)) continue; + class_type->odr_violated = true; + /* If the loops above stopped on non-virtual pointer, we have mismatch in RTTI information mangling. */ - if (!DECL_VIRTUAL_P (ref1->referred->decl) - && !DECL_VIRTUAL_P (ref2->referred->decl)) + if (TREE_CODE (ref1->referred->decl) != FUNCTION_DECL + && TREE_CODE (ref2->referred->decl) != FUNCTION_DECL) { if (warning_at (DECL_SOURCE_LOCATION - (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0, + (TYPE_NAME (DECL_CONTEXT (vtable->decl))), + OPT_Wodr, "virtual table of type %qD violates " "one definition rule ", DECL_CONTEXT (vtable->decl))) @@ -813,12 +835,6 @@ compare_virtual_tables (varpool_node *pr or virtual method. If one points to virtual table and other to method we can complain the same way as if one table was shorter than other pointing out the extra method. */ - gcc_assert (DECL_VIRTUAL_P (ref1->referred->decl) - && (TREE_CODE (ref1->referred->decl) == FUNCTION_DECL - || TREE_CODE (ref1->referred->decl) == VAR_DECL)); - gcc_assert (DECL_VIRTUAL_P (ref2->referred->decl) - && (TREE_CODE (ref2->referred->decl) == FUNCTION_DECL - || TREE_CODE (ref2->referred->decl) == VAR_DECL)); if (TREE_CODE (ref1->referred->decl) != TREE_CODE (ref2->referred->decl)) { @@ -829,6 +845,8 @@ compare_virtual_tables (varpool_node *pr } } + class_type->odr_violated = true; + /* Complain about size mismatch. Either we have too many virutal functions or too many virtual table pointers. */ if (end1 || end2) @@ -841,7 +859,8 @@ compare_virtual_tables (varpool_node *pr ref1 = ref2; } if (warning_at (DECL_SOURCE_LOCATION - (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0, + (TYPE_NAME (DECL_CONTEXT (vtable->decl))), + OPT_Wodr, "virtual table of type %qD violates " "one definition rule", DECL_CONTEXT (vtable->decl))) @@ -871,7 +890,7 @@ compare_virtual_tables (varpool_node *pr /* And in the last case we have either mistmatch in between two virtual methods or two virtual table pointers. */ if (warning_at (DECL_SOURCE_LOCATION - (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0, + (TYPE_NAME (DECL_CONTEXT (vtable->decl))), OPT_Wodr, "virtual table of type %qD violates " "one definition rule ", DECL_CONTEXT (vtable->decl))) @@ -914,8 +933,9 @@ warn_odr (tree t1, tree t2, tree st1, tr if (warned) *warned = false; - if (!warn) + if (!warn || !TYPE_NAME(t1)) return; + if (!warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (t1)), OPT_Wodr, "type %qT violates one definition rule", t1)) @@ -964,7 +984,132 @@ warn_odr (tree t1, tree t2, tree st1, tr void warn_types_mismatch (tree t1, tree t2) { + /* If types have names and they are different, it is most informative to + output those. */ + if (TYPE_NAME (t1) && TYPE_NAME (t2) + && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t1)) + && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t2)) + && DECL_ASSEMBLER_NAME (TYPE_NAME (t1)) + != DECL_ASSEMBLER_NAME (TYPE_NAME (t2))) + { + char *name1 = xstrdup (cplus_demangle + (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (t1))), + DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES)); + char *name2 = cplus_demangle + (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (t2))), + DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES); + if (name1 && name2 && strcmp (name1, name2)) + { + inform (DECL_SOURCE_LOCATION (TYPE_NAME (t1)), + "type name %<%s%> should match type name %<%s%>", + name1, name2); + inform (DECL_SOURCE_LOCATION (TYPE_NAME (t2)), + "the incompatible type is defined here"); + free (name1); + return; + } + free (name1); + } + /* It is a quite common bug to reference anonymous namespace type in + non-anonymous namespace class. */ + if (type_in_anonymous_namespace_p (t1) + || type_in_anonymous_namespace_p (t2)) + { + if (!type_in_anonymous_namespace_p (t1)) + { + tree tmp = t1;; + t1 = t2; + t2 = tmp; + } + if (TYPE_NAME (t1) && TYPE_NAME (t2)) + { + inform (DECL_SOURCE_LOCATION (TYPE_NAME (t1)), + "type %qT defined in anonymous namespace can not match " + "type %qT", + t1, t2); + inform (DECL_SOURCE_LOCATION (TYPE_NAME (t2)), + "the incompatible type defined in anonymous namespace in " + "another translation unit"); + } + else + inform (UNKNOWN_LOCATION, + "types in anonymous namespace does not match across " + "translation unit boundary"); + return; + } + /* A tricky case are component types. Often they appear the same in source + code and the mismatch is dragged in by type they are build from. + Look for those differences in subtypes and try to be informative. In other + cases just output nothing because the source code is probably different + and in this case we already output a all necessary info. */ if (!TYPE_NAME (t1) || !TYPE_NAME (t2)) + { + if (TREE_CODE (t1) == TREE_CODE (t2)) + { + hash_set visited; + if (TREE_CODE (t1) == ARRAY_TYPE + && COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2)) + { + tree i1 = TYPE_DOMAIN (t1); + tree i2 = TYPE_DOMAIN (t2); + + if (i1 && i2 + && TYPE_MAX_VALUE (i1) + && TYPE_MAX_VALUE (i2) + && !operand_equal_p (TYPE_MAX_VALUE (i1), + TYPE_MAX_VALUE (i2), 0)) + { + inform (UNKNOWN_LOCATION, + "array types have different bounds"); + return; + } + } + if ((POINTER_TYPE_P (t1) || TREE_CODE (t1) == ARRAY_TYPE) + && !odr_subtypes_equivalent_p (TREE_TYPE (t1), + TREE_TYPE (t2), + &visited)) + warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2)); + else if (TREE_CODE (t1) == METHOD_TYPE + || TREE_CODE (t1) == FUNCTION_TYPE) + { + tree parms1, parms2; + int count = 1; + + if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2), + &visited)) + { + inform (UNKNOWN_LOCATION, "return value type mismatch"); + warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2)); + return; + } + for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2); + parms1 && parms2; + parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2), + count++) + { + if (!odr_subtypes_equivalent_p + (TREE_VALUE (parms1), TREE_VALUE (parms2), &visited)) + { + inform (UNKNOWN_LOCATION, + "type mismatch in parameter %i", count); + warn_types_mismatch (TREE_VALUE (parms1), + TREE_VALUE (parms2)); + return; + } + } + if (parms1 || parms2) + { + inform (UNKNOWN_LOCATION, + "types have different parameter counts"); + return; + } + } + } + return; + } + /* This should not happen but if it does, the warning would not be helpful. + TODO: turn it into assert next stage1. */ + if (TYPE_NAME (t1) == TYPE_NAME (t2)) return; /* In Firefox it is a common bug to have same types but in different namespaces. Be a bit more informative on @@ -979,12 +1124,19 @@ warn_types_mismatch (tree t1, tree t2) "type %qT should match type %qT but is defined " "in different namespace ", t1, t2); + else if (types_odr_comparable (t1, t2, true) + && types_same_for_odr (t1, t2, true)) + inform (DECL_SOURCE_LOCATION (TYPE_NAME (t1)), + "type %qT should match type %qT that itself violate " + "one definition rule", + t1, t2); else inform (DECL_SOURCE_LOCATION (TYPE_NAME (t1)), "type %qT should match type %qT", t1, t2); - inform (DECL_SOURCE_LOCATION (TYPE_NAME (t2)), - "the incompatible type is defined here"); + if (DECL_SOURCE_LOCATION (TYPE_NAME (t2)) > BUILTINS_LOCATION) + inform (DECL_SOURCE_LOCATION (TYPE_NAME (t2)), + "the incompatible type is defined here"); } /* Compare T1 and T2, report ODR violations if WARN is true and set @@ -1232,6 +1384,20 @@ odr_types_equivalent_p (tree t1, tree t2 /* For aggregate types, all the fields must be the same. */ if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2)) { + if (TYPE_BINFO (t1) && TYPE_BINFO (t2) + && polymorphic_type_binfo_p (TYPE_BINFO (t1)) + != polymorphic_type_binfo_p (TYPE_BINFO (t2))) + { + if (polymorphic_type_binfo_p (TYPE_BINFO (t1))) + warn_odr (t1, t2, NULL, NULL, warn, warned, + G_("a type defined in another translation unit " + "is not polymorphic")); + else + warn_odr (t1, t2, NULL, NULL, warn, warned, + G_("a type defined in another translation unit " + "is polymorphic")); + return false; + } for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2); f1 || f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) @@ -1303,8 +1469,8 @@ odr_types_equivalent_p (tree t1, tree t2 warn_odr (t1, t2, NULL, NULL, warn, warned, G_("a type with different virtual table pointers" " is defined in another translation unit")); - if ((f1 && DECL_ARTIFICIAL (f1)) - || (f2 && DECL_ARTIFICIAL (f2))) + else if ((f1 && DECL_ARTIFICIAL (f1)) + || (f2 && DECL_ARTIFICIAL (f2))) warn_odr (t1, t2, NULL, NULL, warn, warned, G_("a type with different bases is defined " "in another translation unit")); @@ -1408,6 +1574,7 @@ add_type_duplicate (odr_type val, tree t { bool build_bases = false; bool prevail = false; + bool odr_must_violate = false; if (!val->types_set) val->types_set = new hash_set; @@ -1469,27 +1636,7 @@ add_type_duplicate (odr_type val, tree t gcc_assert (in_lto_p); vec_safe_push (val->types, type); - /* First we compare memory layout. */ - if (!odr_types_equivalent_p (val->type, type, - !flag_ltrans && !val->odr_violated, - &warned, &visited)) - { - merge = false; - odr_violation_reported = true; - val->odr_violated = true; - if (symtab->dump_file) - { - fprintf (symtab->dump_file, "ODR violation\n"); - - print_node (symtab->dump_file, "", val->type, 0); - putc ('\n',symtab->dump_file); - print_node (symtab->dump_file, "", type, 0); - putc ('\n',symtab->dump_file); - } - } - - /* Next sanity check that bases are the same. If not, we will end - up producing wrong answers. */ + /* If both are class types, compare the bases. */ if (COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (val->type) && TREE_CODE (val->type) == RECORD_TYPE && TREE_CODE (type) == RECORD_TYPE @@ -1498,25 +1645,28 @@ add_type_duplicate (odr_type val, tree t if (BINFO_N_BASE_BINFOS (TYPE_BINFO (type)) != BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type))) { - if (!warned && !val->odr_violated) + if (!flag_ltrans && !warned && !val->odr_violated) { tree extra_base; warn_odr (type, val->type, NULL, NULL, !warned, &warned, "a type with the same name but different " "number of polymorphic bases is " "defined in another translation unit"); - if (BINFO_N_BASE_BINFOS (TYPE_BINFO (type)) - > BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type))) - extra_base = BINFO_BASE_BINFO - (TYPE_BINFO (type), - BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type))); - else - extra_base = BINFO_BASE_BINFO - (TYPE_BINFO (val->type), - BINFO_N_BASE_BINFOS (TYPE_BINFO (type))); - tree extra_base_type = BINFO_TYPE (extra_base); - inform (DECL_SOURCE_LOCATION (TYPE_NAME (extra_base_type)), - "the extra base is defined here"); + if (warned) + { + if (BINFO_N_BASE_BINFOS (TYPE_BINFO (type)) + > BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type))) + extra_base = BINFO_BASE_BINFO + (TYPE_BINFO (type), + BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type))); + else + extra_base = BINFO_BASE_BINFO + (TYPE_BINFO (val->type), + BINFO_N_BASE_BINFOS (TYPE_BINFO (type))); + tree extra_base_type = BINFO_TYPE (extra_base); + inform (DECL_SOURCE_LOCATION (TYPE_NAME (extra_base_type)), + "the extra base is defined here"); + } } base_mismatch = true; } @@ -1570,10 +1720,10 @@ add_type_duplicate (odr_type val, tree t but not for TYPE2 we possibly missed a base when recording VAL->type earlier. Be sure this does not happen. */ - gcc_assert (TYPE_BINFO (type2) - || !polymorphic_type_binfo_p (TYPE_BINFO (type1)) - || build_bases - || val->odr_violated); + if (TYPE_BINFO (type1) + && polymorphic_type_binfo_p (TYPE_BINFO (type1)) + && !build_bases) + odr_must_violate = true; break; } /* One base is polymorphic and the other not. @@ -1583,38 +1733,15 @@ add_type_duplicate (odr_type val, tree t && polymorphic_type_binfo_p (TYPE_BINFO (type1)) != polymorphic_type_binfo_p (TYPE_BINFO (type2))) { - gcc_assert (val->odr_violated); + if (!warned && !val->odr_violated) + warn_odr (type, val->type, NULL, NULL, + !warned, &warned, + "a base of the type is polymorphic only in one " + "translation unit"); base_mismatch = true; break; } } -#ifdef ENABLE_CHECKING - /* Sanity check that all bases will be build same way again. */ - if (!base_mismatch && val->bases.length ()) - { - unsigned int num_poly_bases = 0; - unsigned int j; - - for (i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++) - if (polymorphic_type_binfo_p (BINFO_BASE_BINFO - (TYPE_BINFO (type), i))) - num_poly_bases++; - gcc_assert (num_poly_bases == val->bases.length ()); - for (j = 0, i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); - i++) - if (polymorphic_type_binfo_p (BINFO_BASE_BINFO - (TYPE_BINFO (type), i))) - { - odr_type base = get_odr_type - (BINFO_TYPE - (BINFO_BASE_BINFO (TYPE_BINFO (type), - i)), - true); - gcc_assert (val->bases[j] == base); - j++; - } - } -#endif if (base_mismatch) { merge = false; @@ -1633,6 +1760,59 @@ add_type_duplicate (odr_type val, tree t } } + /* Next compare memory layout. */ + if (!odr_types_equivalent_p (val->type, type, + !flag_ltrans && !val->odr_violated && !warned, + &warned, &visited)) + { + merge = false; + odr_violation_reported = true; + val->odr_violated = true; + if (symtab->dump_file) + { + fprintf (symtab->dump_file, "ODR violation\n"); + + print_node (symtab->dump_file, "", val->type, 0); + putc ('\n',symtab->dump_file); + print_node (symtab->dump_file, "", type, 0); + putc ('\n',symtab->dump_file); + } + } + gcc_assert (val->odr_violated || !odr_must_violate); + /* Sanity check that all bases will be build same way again. */ +#ifdef ENABLE_CHECKING + if (COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (val->type) + && TREE_CODE (val->type) == RECORD_TYPE + && TREE_CODE (type) == RECORD_TYPE + && TYPE_BINFO (val->type) && TYPE_BINFO (type) + && !val->odr_violated + && !base_mismatch && val->bases.length ()) + { + unsigned int num_poly_bases = 0; + unsigned int j; + + for (i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++) + if (polymorphic_type_binfo_p (BINFO_BASE_BINFO + (TYPE_BINFO (type), i))) + num_poly_bases++; + gcc_assert (num_poly_bases == val->bases.length ()); + for (j = 0, i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); + i++) + if (polymorphic_type_binfo_p (BINFO_BASE_BINFO + (TYPE_BINFO (type), i))) + { + odr_type base = get_odr_type + (BINFO_TYPE + (BINFO_BASE_BINFO (TYPE_BINFO (type), + i)), + true); + gcc_assert (val->bases[j] == base); + j++; + } + } +#endif + + /* Regularize things a little. During LTO same types may come with different BINFOs. Either because their virtual table was not merged by tree merging and only later at decl merging or @@ -1794,7 +1974,7 @@ get_odr_type (tree type, bool insert) tree binfo = TYPE_BINFO (type); unsigned int i; - gcc_assert (BINFO_TYPE (TYPE_BINFO (val->type)) = type); + gcc_assert (BINFO_TYPE (TYPE_BINFO (val->type)) == type); val->all_derivations_known = type_all_derivations_known_p (type); for (i = 0; i < BINFO_N_BASE_BINFOS (binfo); i++) @@ -1803,10 +1983,9 @@ get_odr_type (tree type, bool insert) determine ODR equivalency of these during LTO. */ if (polymorphic_type_binfo_p (BINFO_BASE_BINFO (binfo, i))) { - odr_type base = get_odr_type (BINFO_TYPE (BINFO_BASE_BINFO (binfo, - i)), - true); - gcc_assert (TYPE_MAIN_VARIANT (base->type) == base->type); + tree base_type = BINFO_TYPE (BINFO_BASE_BINFO (binfo, i)); + odr_type base = get_odr_type (base_type, true); + gcc_assert (TYPE_MAIN_VARIANT (base_type) == base_type); base->derived_types.safe_push (val); val->bases.safe_push (base); if (base->id > base_id)