Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -2108,3 +2108,8 @@ let SemaHandler = 0; let Documentation = [Undocumented]; } + +def InternalLinkage : InheritableAttr { + let Spellings = [GCC<"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: 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/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -1573,7 +1573,14 @@ 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; + } + + if (InternalLinkageAttr *Internal = D->getAttr()) { + S.Diag(Attr.getRange().getBegin(), diag::err_attributes_are_not_compatible) + << Attr.getName() << Internal; + S.Diag(Internal->getLocation(), diag::note_conflicting_attribute); return; } @@ -4550,6 +4557,27 @@ 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 (CommonAttr *Common = D->getAttr()) { + S.Diag(Attr.getRange().getBegin(), diag::err_attributes_are_not_compatible) + << Attr.getName() << Common; + S.Diag(Common->getLocation(), diag::note_conflicting_attribute); + return; + } + + if (!D->hasAttr()) + D->addAttr(::new (S.Context) InternalLinkageAttr( + Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); +} + /// 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 +5019,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,85 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -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)); +// CHECK-DAG: @_ZN1A1yE = 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; + +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 +}; +} + +// 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; + ZZZ::A za; + za.g(); + ZZZ::f(); + int &X = ZZZ::x; + B b; + b.f(); + int &X2 = B::x; +} Index: test/Sema/internal_linkage.c =================================================================== --- /dev/null +++ test/Sema/internal_linkage.c @@ -0,0 +1,11 @@ +// 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}} + + __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() { +}