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(); +} + +