diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1794,6 +1794,13 @@ let SimpleHandler = 1; } +def UnnamedAddr : InheritableAttr { + let Spellings = [Clang<"unnamed_addr">]; + let Subjects = SubjectList<[GlobalVar], ErrorDiag>; + let Documentation = [UnnamedAddrDocs]; + let SimpleHandler = 1; +} + def ReturnsTwice : InheritableAttr { let Spellings = [GCC<"returns_twice">]; let Subjects = SubjectList<[Function]>; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -1408,6 +1408,24 @@ }]; } +def UnnamedAddrDocs : Documentation { + let Category = DocCatField; + let Content = [{ +The ``clang::unnamed_addr`` attribute specifies that the address of a global is +not significant. This allows global constants with the same contents to be +merged. This can break global pointer identity, i.e. two different globals have +the same address. + +Example usage: + +.. code-block:: c + + // i and j may have the same address. + [[clang::unnamed_addr]] const int i = 42; + [[clang::unnamed_addr]] const int j = 42; + }]; +} + def ObjCRequiresSuperDocs : Documentation { let Category = DocCatFunction; let Content = [{ diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5254,6 +5254,9 @@ GV->setConstant(true); } + if (D->hasAttr()) + GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + CharUnits AlignVal = getContext().getDeclAlign(D); // Check for alignment specifed in an 'omp allocate' directive. if (std::optional AlignValFromAllocate = diff --git a/clang/test/CodeGen/unnamed-addr.c b/clang/test/CodeGen/unnamed-addr.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/unnamed-addr.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -O1 -emit-llvm -o - -disable-llvm-passes %s | FileCheck %s + +// CHECK: @i = unnamed_addr constant i32 8 + +[[clang::unnamed_addr]] const int i = 8;