diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 3225c98476865..6cb308e5a7597 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -699,6 +699,7 @@ void CodeGenModule::checkAliases() { void CodeGenModule::clear() { DeferredDeclsToEmit.clear(); EmittedDeferredDecls.clear(); + DeferredAnnotations.clear(); if (OpenMPRuntime) OpenMPRuntime->clear(); } @@ -3165,6 +3166,13 @@ void CodeGenModule::EmitVTablesOpportunistically() { } void CodeGenModule::EmitGlobalAnnotations() { + for (const auto& [MangledName, VD] : DeferredAnnotations) { + llvm::GlobalValue *GV = GetGlobalValue(MangledName); + if (GV) + AddGlobalAnnotations(VD, GV); + } + DeferredAnnotations.clear(); + if (Annotations.empty()) return; @@ -3678,6 +3686,14 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Ignore declarations, they will be emitted on their first use. if (const auto *FD = dyn_cast(Global)) { + // Update deferred annotations with the latest declaration if the function + // function was already used or defined. + if (FD->hasAttr()) { + StringRef MangledName = getMangledName(GD); + if (GetGlobalValue(MangledName)) + DeferredAnnotations[MangledName] = FD; + } + // Forward declarations are emitted lazily on first use. if (!FD->doesThisDeclarationHaveABody()) { if (!FD->doesDeclarationForceExternallyVisibleDefinition()) @@ -4462,6 +4478,11 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( llvm::Function::Create(FTy, llvm::Function::ExternalLinkage, Entry ? StringRef() : MangledName, &getModule()); + // Store the declaration associated with this function so it is potentially + // updated by further declarations or definitions and emitted at the end. + if (D && D->hasAttr()) + DeferredAnnotations[MangledName] = cast(D); + // If we already created a function with the same mangled name (but different // type) before, take its name and add it to the list of functions to be // replaced with F at the end of CodeGen. @@ -5748,8 +5769,6 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, AddGlobalCtor(Fn, CA->getPriority()); if (const DestructorAttr *DA = D->getAttr()) AddGlobalDtor(Fn, DA->getPriority(), true); - if (D->hasAttr()) - AddGlobalAnnotations(D, Fn); if (getLangOpts().OpenMP && D->hasAttr()) getOpenMPRuntime().emitDeclareTargetFunction(D, GV); } diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index e81edc979c208..ec34680fd3f7e 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -431,6 +431,10 @@ class CodeGenModule : public CodeGenTypeCache { /// Global annotations. std::vector Annotations; + // Store deferred function annotations so they can be emitted at the end with + // most up to date ValueDecl that will have all the inherited annotations. + llvm::DenseMap DeferredAnnotations; + /// Map used to get unique annotation strings. llvm::StringMap AnnotationStrings; diff --git a/clang/test/CodeGen/annotations-decl-use-decl.c b/clang/test/CodeGen/annotations-decl-use-decl.c new file mode 100644 index 0000000000000..f43ba91a34d87 --- /dev/null +++ b/clang/test/CodeGen/annotations-decl-use-decl.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +// Test annotation attributes are still emitted when the function is used before +// it is defined with annotations. + +void foo(void); +void *xxx = (void*)foo; +void __attribute__((annotate("bar"))) foo(); + +// CHECK: target triple +// CHECK-DAG: private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata" + +// CHECK: @llvm.global.annotations = appending global [1 x { ptr, ptr, ptr, i32, ptr }] [{ +// CHECK-SAME: { ptr @foo, +// CHECK-SAME: }], section "llvm.metadata" + diff --git a/clang/test/CodeGen/annotations-decl-use-define.c b/clang/test/CodeGen/annotations-decl-use-define.c new file mode 100644 index 0000000000000..1ca12cddd3658 --- /dev/null +++ b/clang/test/CodeGen/annotations-decl-use-define.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +// Test annotation attributes are still emitted when the function is used before +// it is defined with annotations. + +void foo(void); +void *xxx = (void*)foo; +void __attribute__((annotate("bar"))) foo() {} + +// CHECK: target triple +// CHECK-DAG: private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata" + +// CHECK: @llvm.global.annotations = appending global [1 x { ptr, ptr, ptr, i32, ptr }] [{ +// CHECK-SAME: { ptr @foo, +// CHECK-SAME: }], section "llvm.metadata" + diff --git a/clang/test/CodeGen/annotations-declaration.c b/clang/test/CodeGen/annotations-declaration.c new file mode 100644 index 0000000000000..2076f4dc030ae --- /dev/null +++ b/clang/test/CodeGen/annotations-declaration.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +// Test annotation attributes are emitted for declarations. + +__attribute__((annotate("bar"))) int foo(); + +int main() { + return foo(); +} + +// CHECK: target triple +// CHECK-DAG: private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata" + +// CHECK: @llvm.global.annotations = appending global [1 x { ptr, ptr, ptr, i32, ptr }] [{ +// CHECK-SAME: { ptr @foo, +// CHECK-SAME: }], section "llvm.metadata" + diff --git a/clang/test/CodeGen/annotations-global.c b/clang/test/CodeGen/annotations-global.c index d6e6f7de8a954..1ae80ef49acd7 100644 --- a/clang/test/CodeGen/annotations-global.c +++ b/clang/test/CodeGen/annotations-global.c @@ -33,15 +33,15 @@ __attribute((address_space(1))) __attribute__((annotate("addrspace1_ann"))) char // CHECK: @llvm.global.annotations = appending global [11 x { ptr, ptr, ptr, i32, ptr }] [{ // CHECK-SAME: { ptr @a.bar, // CHECK-SAME: { ptr @a.bar, -// CHECK-SAME: { ptr @a, -// CHECK-SAME: { ptr @a, -// CHECK-SAME: { ptr @a, -// CHECK-SAME: { ptr @a, // CHECK-SAME: { ptr @sfoo, // CHECK-SAME: { ptr @sfoo, // CHECK-SAME: { ptr @foo, // CHECK-SAME: { ptr @foo, // CHECK-SAME: { ptr addrspacecast (ptr addrspace(1) @addrspace1_var to ptr), +// CHECK-SAME: { ptr @a, +// CHECK-SAME: { ptr @a, +// CHECK-SAME: { ptr @a, +// CHECK-SAME: { ptr @a, // CHECK-SAME: }], section "llvm.metadata" // AS1-GLOBALS: target datalayout = "{{.+}}-A5-G1" diff --git a/clang/test/CodeGenCXX/attr-annotate-constructor.cpp b/clang/test/CodeGenCXX/attr-annotate-constructor.cpp new file mode 100644 index 0000000000000..7a115137f1a67 --- /dev/null +++ b/clang/test/CodeGenCXX/attr-annotate-constructor.cpp @@ -0,0 +1,10 @@ +// RUN: %clang %s -S -emit-llvm -target x86_64-unknown-linux -o - + +// Test annotation attributes on constructors do not crash. + +class Foo { +public: + [[clang::annotate("test")]] Foo() {} +}; + +Foo foo; diff --git a/clang/test/CodeGenCXX/attr-annotate-destructor.cpp b/clang/test/CodeGenCXX/attr-annotate-destructor.cpp new file mode 100644 index 0000000000000..dbe686b04861e --- /dev/null +++ b/clang/test/CodeGenCXX/attr-annotate-destructor.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -S -emit-llvm -triple x86_64-unknown-linux-gnu -o - | FileCheck %s + +// Test annotation attributes on destructors do not crash. + +struct k { + ~k() __attribute__((annotate(""))) {} +}; +void m() { k(); } + +// CHECK: @llvm.global.annotations = appending global [2 x { ptr, ptr, ptr, i32, ptr }] [{ diff --git a/clang/test/CodeGenCXX/attr-annotate.cpp b/clang/test/CodeGenCXX/attr-annotate.cpp index 705a0ef54376f..fd08f208fc9bc 100644 --- a/clang/test/CodeGenCXX/attr-annotate.cpp +++ b/clang/test/CodeGenCXX/attr-annotate.cpp @@ -3,9 +3,9 @@ //CHECK: @[[STR1:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}attr-annotate.cpp\00", section "llvm.metadata" //CHECK: @[[STR2:.*]] = private unnamed_addr constant [4 x i8] c"abc\00", align 1 //CHECK: @[[STR:.*]] = private unnamed_addr constant [5 x i8] c"test\00", section "llvm.metadata" -//CHECK: @[[ARGS:.*]] = private unnamed_addr constant { i32, ptr, i32 } { i32 9, ptr @[[STR2:.*]], i32 8 }, section "llvm.metadata" -//CHECK: @[[ARGS2:.*]] = private unnamed_addr constant { %struct.Struct } { %struct.Struct { ptr @_ZN1AIjLj9EE2SVE, ptr getelementptr (i8, ptr @_ZN1AIjLj9EE2SVE, i64 4) } }, section "llvm.metadata" -//CHECK: @llvm.global.annotations = appending global [2 x { ptr, ptr, ptr, i32, ptr }] [{ ptr, ptr, ptr, i32, ptr } { ptr @_ZN1AIjLj9EE4testILi8EEEvv, ptr @[[STR:.*]], ptr @[[STR1:.*]], i32 {{.*}}, ptr @[[ARGS:.*]] }, { ptr, ptr, ptr, i32, ptr } { ptr @_ZN1AIjLj9EE5test2Ev, ptr @.str.6, ptr @.str.1, i32 24, ptr @[[ARGS2]] }] +//CHECK: @[[ARGS:.*]] = private unnamed_addr constant { %struct.Struct } { %struct.Struct { ptr @_ZN1AIjLj9EE2SVE, ptr getelementptr (i8, ptr @_ZN1AIjLj9EE2SVE, i64 4) } }, section "llvm.metadata" +//CHECK: @[[ARGS2:.*]] = private unnamed_addr constant { i32, ptr, i32 } { i32 9, ptr @[[STR2:.*]], i32 8 }, section "llvm.metadata" +//CHECK: @llvm.global.annotations = appending global [2 x { ptr, ptr, ptr, i32, ptr }] [{ ptr, ptr, ptr, i32, ptr } { ptr @_ZN1AIjLj9EE5test2Ev, ptr @.str.6, ptr @.str.1, i32 24, ptr @[[ARGS]] }, { ptr, ptr, ptr, i32, ptr } { ptr @_ZN1AIjLj9EE4testILi8EEEvv, ptr @[[STR:.*]], ptr @[[STR1:.*]], i32 {{.*}}, ptr @[[ARGS2:.*]] }] constexpr const char* str() { return "abc";