diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 551a883a8fa92fe8bcdcdd7b68fb25b578e30b35..58860b27ad57fd17edab53ce5a7612d257a23984 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -679,9 +679,9 @@ public: return const_cast<Decl*>(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/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 04431ced36a869f310a715d90d0918aaa341911e..08a6490f1400c2305ab6862b855a0198b2d0ff67 100644 --- a/lib/AST/Decl.cpp +++ b/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/test/Modules/Inputs/templates-left.h b/test/Modules/Inputs/templates-left.h index 7ca5cc52a12ff68e63bb1a086651f58893993f12..cbe89434f9f390dfaa0e545f112dad02504a7401 100644 --- a/test/Modules/Inputs/templates-left.h +++ b/test/Modules/Inputs/templates-left.h @@ -66,3 +66,7 @@ namespace EmitDefaultedSpecialMembers { SmallString<256> SS; }; } + +inline int *getStaticDataMemberLeft() { + return WithUndefinedStaticDataMember<int[]>::undefined; +} diff --git a/test/Modules/Inputs/templates-right.h b/test/Modules/Inputs/templates-right.h index 5907cbca73eeddc04b3e93a378c461eebba3e67e..daea97b86b88477cb73c3e1c5fc2d734caf0efdc 100644 --- a/test/Modules/Inputs/templates-right.h +++ b/test/Modules/Inputs/templates-right.h @@ -43,3 +43,7 @@ template<typename T> struct MergePatternDecl; void outOfLineInlineUseRightF(void (OutOfLineInline<int>::*)() = &OutOfLineInline<int>::f); void outOfLineInlineUseRightG(void (OutOfLineInline<int>::*)() = &OutOfLineInline<int>::g); void outOfLineInlineUseRightH(void (OutOfLineInline<int>::*)() = &OutOfLineInline<int>::h); + +inline int *getStaticDataMemberRight() { + return WithUndefinedStaticDataMember<int[]>::undefined; +} diff --git a/test/Modules/Inputs/templates-top.h b/test/Modules/Inputs/templates-top.h index b1e0548d41e9b1dfe7313d51af34c1baf7b7d10a..31f5e4199281990a9638698e6eb28e5a00a19aa0 100644 --- a/test/Modules/Inputs/templates-top.h +++ b/test/Modules/Inputs/templates-top.h @@ -53,3 +53,7 @@ namespace EmitDefaultedSpecialMembers { // trivial dtor }; } + +template<typename T> struct WithUndefinedStaticDataMember { + static T undefined; +}; diff --git a/test/Modules/templates.mm b/test/Modules/templates.mm index 78348af41e778b718e4274fadd1c309f21ea6b16..67a1e070e23b464467521fa0a1b8ea87b7d27318 100644 --- a/test/Modules/templates.mm +++ b/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<int> vec_int; @@ -100,3 +101,17 @@ template struct ExplicitInstantiation<false, true>; template struct ExplicitInstantiation<true, true>; void testDelayUpdatesImpl() { testDelayUpdates<int>(); } + +void testStaticDataMember() { + WithUndefinedStaticDataMember<int[]> 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(); +} + +