eugenis updated this revision to Diff 38679.
Repository:
rL LLVM
http://reviews.llvm.org/D13925
Files:
include/clang/Basic/Attr.td
include/clang/Basic/AttrDocs.td
include/clang/Sema/Sema.h
lib/AST/Decl.cpp
lib/Sema/Sema.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/CodeGenCXX/attribute_internal_linkage.cpp
test/Sema/internal_linkage.c
test/SemaCXX/internal_linkage.cpp
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() {
+}
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/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: 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<InternalLinkageAttr>()) {
+ 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<CommonAttr>()) {
+ 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<OptimizeNoneAttr>()) {
@@ -4550,6 +4579,20 @@
Attr.getAttributeSpellingListIndex()));
}
+static void handleInternalLinkageAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!(isa<FunctionDecl>(D) || isa<VarDecl>(D) || isa<TagDecl>(D) ||
+ isa<NamespaceDecl>(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<OpenCLImageAccessAttr>(S, D, Attr);
break;
+ case AttributeList::AT_InternalLinkage:
+ handleInternalLinkageAttr(S, D, Attr);
+ break;
// Microsoft attributes:
case AttributeList::AT_MSNoVTable:
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<OptimizeNoneAttr>(Attr))
NewAttr = S.mergeOptimizeNoneAttr(D, OA->getRange(), AttrSpellingListIndex);
+ else if (const auto *InternalLinkageA = dyn_cast<InternalLinkageAttr>(Attr))
+ NewAttr = S.mergeInternalLinkageAttr(D, InternalLinkageA->getRange(),
+ AttrSpellingListIndex);
+ else if (const auto *CommonA = dyn_cast<CommonAttr>(Attr))
+ NewAttr = S.mergeCommonAttr(D, CommonA->getRange(), AttrSpellingListIndex);
else if (isa<AlignedAttr>(Attr))
// AlignedAttrs are handled separately, because we need to handle all
// such attributes on a declaration at the same time.
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<InternalLinkageAttr>()) {
S.Diag(ND->getLocation(), diag::warn_undefined_internal)
<< isa<VarDecl>(ND) << ND;
} else {
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -633,6 +633,13 @@
}
assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");
+ for (const DeclContext *DC = D->getDeclContext();
+ !isa<TranslationUnitDecl>(DC); DC = DC->getParent()) {
+ const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC);
+ if (ND && ND->getAttr<InternalLinkageAttr>())
+ return LinkageInfo::internal();
+ }
+
if (D->isInAnonymousNamespace()) {
const VarDecl *Var = dyn_cast<VarDecl>(D);
const FunctionDecl *Func = dyn_cast<FunctionDecl>(D);
@@ -1224,6 +1231,10 @@
static LinkageInfo computeLVForDecl(const NamedDecl *D,
LVComputationKind computation) {
+ // Internal_linkage attribute overrides other considerations.
+ if (D->hasAttr<InternalLinkageAttr>())
+ 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<InternalLinkageAttr>() !=
+ D->hasAttr<InternalLinkageAttr>()));
#endif
return LV;
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -2116,6 +2116,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: 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/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];
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits