[cfe-commits] r167906 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/Sema/DeclSpec.h lib/AST/ASTContext.cpp lib/AST/Decl.cpp lib/AST/ItaniumMangle.cpp lib/Sema/SemaDecl.cpp test/CodeGenCXX/mangle.cpp test/CodeGenCXX/template-anonymous-types.cpp test/SemaCXX/warn-unused-filescoped.cpp
David Blaikie
dblaikie at gmail.com
Tue Nov 13 17:52:06 PST 2012
Author: dblaikie
Date: Tue Nov 13 19:52:05 2012
New Revision: 167906
URL: http://llvm.org/viewvc/llvm-project?rev=167906&view=rev
Log:
Provide the correct mangling and linkage for certain unnamed nested classes.
This corrects the mangling and linkage of classes (& their member functions) in
cases like this:
struct foo {
struct {
void func() { ... }
} x;
};
we were accidentally giving this nested unnamed struct 'no' linkage where it
should've had the linkage of the outer class. The mangling was incorrecty too,
mangling as TU-wide unnamed type mangling of $_X rather than class-scoped
mangling of UtX_.
This also fixes -Wunused-member-function which would incorrectly diagnose
'func' as unused due to it having no linkage & thus appearing to be TU-local
when in fact it might be correctly used in another TU.
Similar mangling should be applied to function local classes in similar cases
but I've deferred that for a subsequent patch.
Review/discussion by Richard Smith, John McCall, & especially Eli Friedman.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/Sema/DeclSpec.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/ItaniumMangle.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/CodeGenCXX/mangle.cpp
cfe/trunk/test/CodeGenCXX/template-anonymous-types.cpp
cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=167906&r1=167905&r2=167906&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Nov 13 19:52:05 2012
@@ -343,7 +343,10 @@
/// \brief Mapping from each declaration context to its corresponding lambda
/// mangling context.
llvm::DenseMap<const DeclContext *, LambdaMangleContext> LambdaMangleContexts;
-
+
+ llvm::DenseMap<const DeclContext *, unsigned> UnnamedMangleContexts;
+ llvm::DenseMap<const TagDecl *, unsigned> UnnamedMangleNumbers;
+
/// \brief Mapping that stores parameterIndex values for ParmVarDecls when
/// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex.
typedef llvm::DenseMap<const VarDecl *, unsigned> ParameterIndexTable;
@@ -1989,6 +1992,9 @@
/// it is not used.
bool DeclMustBeEmitted(const Decl *D);
+ void addUnnamedTag(const TagDecl *Tag);
+ int getUnnamedTagManglingNumber(const TagDecl *Tag) const;
+
/// \brief Retrieve the lambda mangling number for a lambda expression.
unsigned getLambdaManglingNumber(CXXMethodDecl *CallOperator);
Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=167906&r1=167905&r2=167906&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Tue Nov 13 19:52:05 2012
@@ -377,16 +377,16 @@
static bool isExprRep(TST T) {
return (T == TST_typeofExpr || T == TST_decltype);
}
+
+ DeclSpec(const DeclSpec &) LLVM_DELETED_FUNCTION;
+ void operator=(const DeclSpec &) LLVM_DELETED_FUNCTION;
+public:
static bool isDeclRep(TST T) {
return (T == TST_enum || T == TST_struct ||
T == TST_interface || T == TST_union ||
T == TST_class);
}
- DeclSpec(const DeclSpec &) LLVM_DELETED_FUNCTION;
- void operator=(const DeclSpec &) LLVM_DELETED_FUNCTION;
-public:
-
DeclSpec(AttributeFactory &attrFactory)
: StorageClassSpec(SCS_unspecified),
SCS_thread_specified(false),
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=167906&r1=167905&r2=167906&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Nov 13 19:52:05 2012
@@ -7508,6 +7508,23 @@
+ llvm::capacity_in_bytes(ClassScopeSpecializationPattern);
}
+void ASTContext::addUnnamedTag(const TagDecl *Tag) {
+ // FIXME: This mangling should be applied to function local classes too
+ if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl() ||
+ !isa<CXXRecordDecl>(Tag->getParent()) || Tag->getLinkage() != ExternalLinkage)
+ return;
+
+ std::pair<llvm::DenseMap<const DeclContext *, unsigned>::iterator, bool> P =
+ UnnamedMangleContexts.insert(std::make_pair(Tag->getParent(), 0));
+ UnnamedMangleNumbers.insert(std::make_pair(Tag, P.first->second++));
+}
+
+int ASTContext::getUnnamedTagManglingNumber(const TagDecl *Tag) const {
+ llvm::DenseMap<const TagDecl *, unsigned>::const_iterator I =
+ UnnamedMangleNumbers.find(Tag);
+ return I != UnnamedMangleNumbers.end() ? I->second : -1;
+}
+
unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) {
CXXRecordDecl *Lambda = CallOperator->getParent();
return LambdaMangleContexts[Lambda->getDeclContext()]
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=167906&r1=167905&r2=167906&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Nov 13 19:52:05 2012
@@ -480,8 +480,7 @@
if (!(isa<CXXMethodDecl>(D) ||
isa<VarDecl>(D) ||
isa<FieldDecl>(D) ||
- (isa<TagDecl>(D) &&
- (D->getDeclName() || cast<TagDecl>(D)->getTypedefNameForAnonDecl()))))
+ isa<TagDecl>(D)))
return LinkageInfo::none();
LinkageInfo LV;
@@ -2561,8 +2560,7 @@
void TagDecl::startDefinition() {
IsBeingDefined = true;
- if (isa<CXXRecordDecl>(this)) {
- CXXRecordDecl *D = cast<CXXRecordDecl>(this);
+ if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(this)) {
struct CXXRecordDecl::DefinitionData *Data =
new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I)
Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=167906&r1=167905&r2=167906&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Nov 13 19:52:05 2012
@@ -1117,6 +1117,18 @@
break;
}
}
+
+ int UnnamedMangle = Context.getASTContext().getUnnamedTagManglingNumber(TD);
+ if (UnnamedMangle != -1) {
+ Out << "Ut";
+ if (UnnamedMangle != 0)
+ Out << llvm::utostr(UnnamedMangle - 1);
+ Out << '_';
+ break;
+ }
+
+ //assert(cast<RecordDecl>(RD)->isAnonymousStructOrUnion() && "Don't mangle unnamed things as "
+ // "anonymous things");
// Get a unique id for the anonymous struct.
uint64_t AnonStructId = Context.getAnonymousStructId(TD);
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=167906&r1=167905&r2=167906&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Nov 13 19:52:05 2012
@@ -2655,6 +2655,7 @@
}
if (Tag) {
+ getASTContext().addUnnamedTag(Tag);
Tag->setFreeStanding();
if (Tag->isInvalidDecl())
return Tag;
@@ -7355,6 +7356,10 @@
if (Decl *D = Group[i])
Decls.push_back(D);
+ if (DeclSpec::isDeclRep(DS.getTypeSpecType()))
+ if (const TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl()))
+ getASTContext().addUnnamedTag(Tag);
+
return BuildDeclaratorGroup(Decls.data(), Decls.size(),
DS.getTypeSpecType() == DeclSpec::TST_auto);
}
Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=167906&r1=167905&r2=167906&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Tue Nov 13 19:52:05 2012
@@ -218,7 +218,7 @@
// PR5139
// CHECK: @_ZN2S7C1Ev
// CHECK: @_ZN2S7C2Ev
-// CHECK: @"_ZN2S73$_0C1Ev"
+// CHECK: @_ZN2S7Ut_C1Ev
S7::S7() {}
// PR5063
@@ -852,3 +852,23 @@
// CHECK: define weak_odr {{.*}} @_ZN6test362f1IJifEEENS_1AIXsZfp_EEEDpT_
template A<2> f1(int, float);
}
+
+namespace test37 {
+ struct foo {
+ struct {
+ } a;
+ typedef struct { } b;
+ typedef struct { } *c;
+ struct {
+ } d;
+ };
+ template<typename T> void func(T) { }
+ void test() {
+ // CHECK: define linkonce_odr void @_ZN6test374funcINS_3fooUt_EEEvT_
+ func(foo().a);
+ // CHECK: define linkonce_odr void @_ZN6test374funcINS_3fooUt0_EEEvT_
+ func(*foo::c());
+ // CHECK: define linkonce_odr void @_ZN6test374funcINS_3fooUt1_EEEvT_
+ func(foo().d);
+ }
+}
Modified: cfe/trunk/test/CodeGenCXX/template-anonymous-types.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/template-anonymous-types.cpp?rev=167906&r1=167905&r2=167906&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/template-anonymous-types.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/template-anonymous-types.cpp Tue Nov 13 19:52:05 2012
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm -w -o - | FileCheck %s
struct S {
enum { FOO = 42 };
@@ -17,21 +17,21 @@
}
void test() {
- // Look for two instantiations, entirely internal to this TU, one for FOO's
+ // Look for two instantiations, one for FOO's
// type and one for BAR's.
- // CHECK: define internal i32 @"_Z1fIN1S3$_0EEiT_"(i32 %t)
+ // CHECK: define linkonce_odr i32 @_Z1fIN1SUt_EEiT_(i32 %t)
(void)f(S::FOO);
- // CHECK: define internal i32 @"_Z1fIN1S3$_1EEiT_"(i32 %t)
+ // CHECK: define linkonce_odr i32 @_Z1fIN1SUt0_EEiT_(i32 %t)
(void)f(S::BAR);
// Now check for the class template instantiations. Annoyingly, they are in
// reverse order.
//
// BAR's instantiation of X:
- // CHECK: define internal i32 @"_ZN1XIN1S3$_1EE1fEv"(%struct.X* %this)
- // CHECK: define internal void @"_ZN1XIN1S3$_1EEC2ES1_"(%struct.X* %this, i32 %t) unnamed_addr
+ // CHECK: define linkonce_odr i32 @_ZN1XIN1SUt0_EE1fEv(%struct.X* %this)
+ // CHECK: define linkonce_odr void @_ZN1XIN1SUt0_EEC2ES1_(%struct.X* %this, i32 %t) unnamed_addr
//
// FOO's instantiation of X:
- // CHECK: define internal i32 @"_ZN1XIN1S3$_0EE1fEv"(%struct.X.0* %this)
- // CHECK: define internal void @"_ZN1XIN1S3$_0EEC2ES1_"(%struct.X.0* %this, i32 %t) unnamed_addr
+ // CHECK: define linkonce_odr i32 @_ZN1XIN1SUt_EE1fEv(%struct.X.0* %this)
+ // CHECK: define linkonce_odr void @_ZN1XIN1SUt_EEC2ES1_(%struct.X.0* %this, i32 %t) unnamed_addr
}
Modified: cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp?rev=167906&r1=167905&r2=167906&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-unused-filescoped.cpp Tue Nov 13 19:52:05 2012
@@ -101,3 +101,20 @@
static const double d = 0.0;
int y = sizeof(d);
}
+
+namespace unused_nested {
+ class outer {
+ void func1();
+ struct {
+ void func2() {
+ }
+ } x;
+ };
+}
+
+namespace unused {
+ struct {
+ void func() { // expected-warning {{unused member function}}
+ }
+ } x; // expected-warning {{unused variable}}
+}
More information about the cfe-commits
mailing list