From 73b21d8fa15295bca14f2ef7328cc295ab7761f3 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 3 Sep 2014 02:33:22 +0000 Subject: [PATCH] [modules] Use DeclContext::equals rather than == on DeclContext* when determining whether a declaration is out of line, instead of assuming that the semantic and lexical DeclContext will be the same declaration whenever they're the same entity. This fixes behavior of declarations within merged classes and enums. llvm-svn: 217008 --- clang/include/clang/AST/DeclBase.h | 6 +++--- clang/lib/AST/Decl.cpp | 5 +++++ clang/test/Modules/Inputs/templates-left.h | 4 ++++ clang/test/Modules/Inputs/templates-right.h | 4 ++++ clang/test/Modules/Inputs/templates-top.h | 4 ++++ clang/test/Modules/templates.mm | 23 +++++++++++++++++---- 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 551a883a8fa9..58860b27ad57 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -679,9 +679,9 @@ public: return const_cast(this)->getLexicalDeclContext(); } - virtual bool isOutOfLine() const { - return getLexicalDeclContext() != getDeclContext(); - } + /// Determine whether this declaration is declared out of line (outside its + /// semantic context). + virtual bool isOutOfLine() const; /// setDeclContext - Set both the semantic and lexical DeclContext /// to DC. diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 04431ced36a8..08a6490f1400 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -38,6 +38,11 @@ Decl *clang::getPrimaryMergedDecl(Decl *D) { return D->getASTContext().getPrimaryMergedDecl(D); } +// Defined here so that it can be inlined into its direct callers. +bool Decl::isOutOfLine() const { + return !getLexicalDeclContext()->Equals(getDeclContext()); +} + //===----------------------------------------------------------------------===// // NamedDecl Implementation //===----------------------------------------------------------------------===// diff --git a/clang/test/Modules/Inputs/templates-left.h b/clang/test/Modules/Inputs/templates-left.h index 7ca5cc52a12f..cbe89434f9f3 100644 --- a/clang/test/Modules/Inputs/templates-left.h +++ b/clang/test/Modules/Inputs/templates-left.h @@ -66,3 +66,7 @@ namespace EmitDefaultedSpecialMembers { SmallString<256> SS; }; } + +inline int *getStaticDataMemberLeft() { + return WithUndefinedStaticDataMember::undefined; +} diff --git a/clang/test/Modules/Inputs/templates-right.h b/clang/test/Modules/Inputs/templates-right.h index 5907cbca73ee..daea97b86b88 100644 --- a/clang/test/Modules/Inputs/templates-right.h +++ b/clang/test/Modules/Inputs/templates-right.h @@ -43,3 +43,7 @@ template struct MergePatternDecl; void outOfLineInlineUseRightF(void (OutOfLineInline::*)() = &OutOfLineInline::f); void outOfLineInlineUseRightG(void (OutOfLineInline::*)() = &OutOfLineInline::g); void outOfLineInlineUseRightH(void (OutOfLineInline::*)() = &OutOfLineInline::h); + +inline int *getStaticDataMemberRight() { + return WithUndefinedStaticDataMember::undefined; +} diff --git a/clang/test/Modules/Inputs/templates-top.h b/clang/test/Modules/Inputs/templates-top.h index b1e0548d41e9..31f5e4199281 100644 --- a/clang/test/Modules/Inputs/templates-top.h +++ b/clang/test/Modules/Inputs/templates-top.h @@ -53,3 +53,7 @@ namespace EmitDefaultedSpecialMembers { // trivial dtor }; } + +template struct WithUndefinedStaticDataMember { + static T undefined; +}; diff --git a/clang/test/Modules/templates.mm b/clang/test/Modules/templates.mm index 78348af41e77..67a1e070e23b 100644 --- a/clang/test/Modules/templates.mm +++ b/clang/test/Modules/templates.mm @@ -12,10 +12,11 @@ void testInlineRedeclEarly() { @import templates_right; -// CHECK: @list_left = global { %{{.*}}*, i32, [4 x i8] } { %{{.*}}* null, i32 8, -// CHECK: @list_right = global { %{{.*}}*, i32, [4 x i8] } { %{{.*}}* null, i32 12, -// CHECK: @_ZZ15testMixedStructvE1l = {{.*}} constant { %{{.*}}*, i32, [4 x i8] } { %{{.*}}* null, i32 1, -// CHECK: @_ZZ15testMixedStructvE1r = {{.*}} constant { %{{.*}}*, i32, [4 x i8] } { %{{.*}}* null, i32 2, +// CHECK-DAG: @list_left = global { %{{.*}}*, i32, [4 x i8] } { %{{.*}}* null, i32 8, +// CHECK-DAG: @list_right = global { %{{.*}}*, i32, [4 x i8] } { %{{.*}}* null, i32 12, +// CHECK-DAG: @_ZZ15testMixedStructvE1l = {{.*}} constant { %{{.*}}*, i32, [4 x i8] } { %{{.*}}* null, i32 1, +// CHECK-DAG: @_ZZ15testMixedStructvE1r = {{.*}} constant { %{{.*}}*, i32, [4 x i8] } { %{{.*}}* null, i32 2, +// CHECK-DAG: @_ZN29WithUndefinedStaticDataMemberIA_iE9undefinedE = external global void testTemplateClasses() { Vector vec_int; @@ -100,3 +101,17 @@ template struct ExplicitInstantiation; template struct ExplicitInstantiation; void testDelayUpdatesImpl() { testDelayUpdates(); } + +void testStaticDataMember() { + WithUndefinedStaticDataMember load_it; + + // CHECK-LABEL: define linkonce_odr i32* @_Z23getStaticDataMemberLeftv( + // CHECK: ret i32* getelementptr inbounds ([0 x i32]* @_ZN29WithUndefinedStaticDataMemberIA_iE9undefinedE, i32 0, i32 0) + (void) getStaticDataMemberLeft(); + + // CHECK-LABEL: define linkonce_odr i32* @_Z24getStaticDataMemberRightv( + // CHECK: ret i32* getelementptr inbounds ([0 x i32]* @_ZN29WithUndefinedStaticDataMemberIA_iE9undefinedE, i32 0, i32 0) + (void) getStaticDataMemberRight(); +} + +