Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -2121,3 +2121,8 @@ let SemaHandler = 0; let Documentation = [Undocumented]; } + +def InternalLinkage : InheritableAttr { + let Spellings = [GNU<"internal_linkage">, CXX11<"clang", "internal_linkage">]; + let Documentation = [InternalLinkageDocs]; +} Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -1612,3 +1612,10 @@ arguments, with arbitrary offsets. }]; } + +def InternalLinkageDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``internal_linkage`` attribute changes the linkage type of the declaration to internal. + }]; +} Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -2106,6 +2106,10 @@ unsigned AttrSpellingListIndex); OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex); + InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex); + CommonAttr *mergeCommonAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex); void mergeDeclAttributes(NamedDecl *New, Decl *Old, AvailabilityMergeKind AMK = AMK_Redeclaration); Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -633,6 +633,13 @@ } assert(!isa(D) && "Didn't expect a FieldDecl!"); + for (const DeclContext *DC = D->getDeclContext(); + !isa(DC); DC = DC->getParent()) { + const NamespaceDecl *ND = dyn_cast(DC); + if (ND && ND->getAttr()) + return LinkageInfo::internal(); + } + if (D->isInAnonymousNamespace()) { const VarDecl *Var = dyn_cast(D); const FunctionDecl *Func = dyn_cast(D); @@ -1224,6 +1231,10 @@ static LinkageInfo computeLVForDecl(const NamedDecl *D, LVComputationKind computation) { + // Internal_linkage attribute overrides other considerations. + if (D->hasAttr()) + return LinkageInfo::internal(); + // Objective-C: treat all Objective-C declarations as having external // linkage. switch (D->getKind()) { @@ -1344,7 +1355,11 @@ break; } } - assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage()); + // Linkages may also differ if one of the declarations has + // InternalLinkageAttr. + assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage() || + (Old->hasAttr() != + D->hasAttr())); #endif return LV; Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -536,7 +536,7 @@ continue; } - if (!ND->isExternallyVisible()) { + if (!ND->isExternallyVisible() || ND->hasAttr()) { S.Diag(ND->getLocation(), diag::warn_undefined_internal) << isa(ND) << ND; } else { Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -2216,6 +2216,11 @@ NewAttr = S.mergeMinSizeAttr(D, MA->getRange(), AttrSpellingListIndex); else if (const auto *OA = dyn_cast(Attr)) NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex); + else if (const auto *InternalLinkageA = dyn_cast(Attr)) + NewAttr = S.mergeInternalLinkageAttr(D, InternalLinkageA->getRange(), + AttrSpellingListIndex); + else if (const auto *CommonA = dyn_cast(Attr)) + NewAttr = S.mergeCommonAttr(D, CommonA->getRange(), AttrSpellingListIndex); else if (isa(Attr)) // AlignedAttrs are handled separately, because we need to handle all // such attributes on a declaration at the same time. Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -1573,12 +1573,13 @@ static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.CPlusPlus) { S.Diag(Attr.getLoc(), diag::err_attribute_not_supported_in_lang) - << Attr.getName() << AttributeLangSupport::Cpp; + << Attr.getName() << AttributeLangSupport::Cpp; return; } - D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + if (CommonAttr *CA = S.mergeCommonAttr(D, Attr.getRange(), + Attr.getAttributeSpellingListIndex())) + D->addAttr(CA); } static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { @@ -3299,6 +3300,34 @@ AttrSpellingListIndex); } +CommonAttr *Sema::mergeCommonAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex) { + + if (InternalLinkageAttr *Internal = D->getAttr()) { + Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) + << "'common'" << Internal; + Diag(Internal->getLocation(), diag::note_conflicting_attribute); + return nullptr; + } + + return ::new (Context) CommonAttr(Range, Context, AttrSpellingListIndex); +} + +InternalLinkageAttr * +Sema::mergeInternalLinkageAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex) { + + if (CommonAttr *Common = D->getAttr()) { + Diag(Range.getBegin(), diag::err_attributes_are_not_compatible) + << "'internal_linkage'" << Common; + Diag(Common->getLocation(), diag::note_conflicting_attribute); + return nullptr; + } + + return ::new (Context) + InternalLinkageAttr(Range, Context, AttrSpellingListIndex); +} + MinSizeAttr *Sema::mergeMinSizeAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex) { if (OptimizeNoneAttr *Optnone = D->getAttr()) { @@ -4550,6 +4579,20 @@ Attr.getAttributeSpellingListIndex())); } +static void handleInternalLinkageAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!(isa(D) || isa(D) || isa(D) || + isa(D))) { + S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored) + << Attr.getName(); + return; + } + + if (InternalLinkageAttr *Internal = S.mergeInternalLinkageAttr( + D, Attr.getRange(), Attr.getAttributeSpellingListIndex())) + D->addAttr(Internal); +} + /// Handles semantic checking for features that are common to all attributes, /// such as checking whether a parameter was properly specified, or the correct /// number of arguments were passed, etc. @@ -4991,6 +5034,9 @@ case AttributeList::AT_OpenCLImageAccess: handleSimpleAttribute(S, D, Attr); break; + case AttributeList::AT_InternalLinkage: + handleInternalLinkageAttr(S, D, Attr); + break; // Microsoft attributes: case AttributeList::AT_MSNoVTable: Index: test/CodeGenCXX/attribute_internal_linkage.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/attribute_internal_linkage.cpp @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++11 -emit-llvm -o - %s | FileCheck %s + +__attribute__((internal_linkage)) static void f() {} +// CHECK-DAG: define internal void @_ZL1fv + +class A { +public: + static int y __attribute__((internal_linkage)); + static int y2 [[clang::internal_linkage]]; +// CHECK-DAG: @_ZN1A1yE = internal global +// CHECK-DAG: @_ZN1A2y2E = internal global + void f1() __attribute__((internal_linkage)); +// CHECK-DAG: define internal void @_ZN1A2f1Ev + void f2() __attribute__((internal_linkage)) {} +// CHECK-DAG: define internal void @_ZN1A2f2Ev + void f3(); +// CHECK-DAG: define internal void @_ZN1A2f3Ev + static void f4() __attribute__((internal_linkage)) {} +// CHECK-DAG: define internal void @_ZN1A2f4Ev + A() __attribute__((internal_linkage)) {} +// CHECK-DAG: define internal void @_ZN1AC1Ev +// CHECK-DAG: define internal void @_ZN1AC2Ev + ~A() __attribute__((internal_linkage)) {} +// CHECK-DAG: define internal void @_ZN1AD1Ev +// CHECK-DAG: define internal void @_ZN1AD2Ev +}; + +int A::y; +int A::y2; + +void A::f1() { +} + +__attribute__((internal_linkage)) void A::f3() { +} + +// Internal_linkage on a namespace affects everything within. +namespace ZZZ __attribute__((internal_linkage)) { +int x; +// CHECK-DAG: @_ZNL3ZZZL1xE = internal global +void f() {} +// CHECK-DAG: define internal void @_ZNL3ZZZL1fEv +class A { +public: + A() {} +// CHECK-DAG: define internal void @_ZNL3ZZZL1AC1Ev +// CHECK-DAG: define internal void @_ZNL3ZZZL1AC2Ev + ~A() {} +// CHECK-DAG: define internal void @_ZNL3ZZZL1AD1Ev +// CHECK-DAG: define internal void @_ZNL3ZZZL1AD2Ev + void g() {}; +// CHECK-DAG: define internal void @_ZNL3ZZZL1A1gEv +}; +} + +namespace ZZZ { +int x2; +// CHECK-DAG: @_ZN3ZZZ2x2E = global i32 +} + +namespace [[clang::internal_linkage]] ZZZ { +int x3; +// CHECK-DAG: @_ZNL3ZZZL2x3E = internal global +} + +// Internal_linkage on a class affects all its members. +class __attribute__((internal_linkage)) B { +public: + B() {} + // CHECK-DAG: define internal void @_ZNL1BC1Ev + // CHECK-DAG: define internal void @_ZNL1BC2Ev + ~B() {} + // CHECK-DAG: define internal void @_ZNL1BD1Ev + // CHECK-DAG: define internal void @_ZNL1BD2Ev + void f() {}; + // CHECK-DAG: define internal void @_ZNL1B1fEv + static int x; + // CHECK-DAG: @_ZNL1B1xE = internal global +}; + +int B::x; + +void use() { + A a; + a.f1(); + a.f2(); + a.f3(); + A::f4(); + f(); + int &Y = A::y; + int &Y2 = A::y2; + ZZZ::A za; + za.g(); + ZZZ::f(); + int &X = ZZZ::x; + int &X2 = ZZZ::x2; + int &X3= ZZZ::x3; + B b; + b.f(); + int &XX2 = B::x; +} Index: test/Sema/internal_linkage.c =================================================================== --- /dev/null +++ test/Sema/internal_linkage.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int var __attribute__((internal_linkage)); +int var2 __attribute__((internal_linkage,common)); // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} \ + // expected-note{{conflicting attribute is here}} +int var3 __attribute__((common,internal_linkage)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} \ + // expected-note{{conflicting attribute is here}} + +int var4 __attribute__((common)); // expected-error{{'common' and 'internal_linkage' attributes are not compatible}} +int var4 __attribute__((internal_linkage)); // expected-note{{conflicting attribute is here}} + +int var5 __attribute__((internal_linkage)); // expected-error{{'internal_linkage' and 'common' attributes are not compatible}} +int var5 __attribute__((common)); // expected-note{{conflicting attribute is here}} + + __attribute__((internal_linkage)) int f() {} +struct __attribute__((internal_linkage)) S { +}; Index: test/SemaCXX/internal_linkage.cpp =================================================================== --- /dev/null +++ test/SemaCXX/internal_linkage.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int f() __attribute__((internal_linkage)); +class __attribute__((internal_linkage)) A { +public: + int x __attribute__((internal_linkage)); // expected-warning{{'internal_linkage' attribute ignored}} + static int y __attribute__((internal_linkage)); + void f1() __attribute__((internal_linkage)); + void f2() __attribute__((internal_linkage)) {} + static void f3() __attribute__((internal_linkage)) {} + A() __attribute__((internal_linkage)) {} + ~A() __attribute__((internal_linkage)) {} + A& operator=(const A&) __attribute__((internal_linkage)) { return *this; } + struct { + int z __attribute__((internal_linkage)); // expected-warning{{'internal_linkage' attribute ignored}} + }; +}; + +namespace Z __attribute__((internal_linkage)) { +} + +int A::y; + +void A::f1() { +}