summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2013-09-07 06:59:46 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2013-09-07 06:59:46 +0000
commit59c0ec23966acc3f6f2631b6cf09e56d2f2c2af0 (patch)
tree80e511242550c55e3c00d3da77a83da4a37ac49b /clang/lib/AST
parent76e98feb578c0cba1500554227699dafd9afe600 (diff)
downloadbcm5719-llvm-59c0ec23966acc3f6f2631b6cf09e56d2f2c2af0.tar.gz
bcm5719-llvm-59c0ec23966acc3f6f2631b6cf09e56d2f2c2af0.zip
AST: __uuidof should leak through templated types
Summary: __uuidof on templated types should exmaine if any of its template parameters have a uuid declspec. If exactly one does, then take it. Otherwise, issue an appropriate error. Reviewers: rsmith, thakis, rnk CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1419 llvm-svn: 190240
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/ExprCXX.cpp53
1 files changed, 47 insertions, 6 deletions
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 7f1a287d1fa..d87c60a733b 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -53,7 +53,8 @@ QualType CXXUuidofExpr::getTypeOperand() const {
}
// static
-UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT) {
+UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT,
+ bool *RDHasMultipleGUIDsPtr) {
// Optionally remove one level of pointer, reference or array indirection.
const Type *Ty = QT.getTypePtr();
if (QT->isPointerType() || QT->isReferenceType())
@@ -63,11 +64,51 @@ UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT) {
// Loop all record redeclaration looking for an uuid attribute.
CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
- for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(),
- E = RD->redecls_end(); I != E; ++I) {
- if (UuidAttr *Uuid = I->getAttr<UuidAttr>())
- return Uuid;
- }
+ if (!RD)
+ return 0;
+
+ if (ClassTemplateSpecializationDecl *CTSD =
+ dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
+ const TemplateArgumentList &TAL = CTSD->getTemplateArgs();
+ UuidAttr *UuidForRD = 0;
+
+ for (unsigned I = 0, N = TAL.size(); I != N; ++I) {
+ const TemplateArgument &TA = TAL[I];
+ bool SeenMultipleGUIDs = false;
+
+ UuidAttr *UuidForTA = 0;
+ if (TA.getKind() == TemplateArgument::Type)
+ UuidForTA = GetUuidAttrOfType(TA.getAsType(), &SeenMultipleGUIDs);
+ else if (TA.getKind() == TemplateArgument::Declaration)
+ UuidForTA =
+ GetUuidAttrOfType(TA.getAsDecl()->getType(), &SeenMultipleGUIDs);
+
+ // If the template argument has a UUID, there are three cases:
+ // - This is the first UUID seen for this RecordDecl.
+ // - This is a different UUID than previously seed for this RecordDecl.
+ // - This is the same UUID than previously seed for this RecordDecl.
+ if (UuidForTA) {
+ if (!UuidForRD)
+ UuidForRD = UuidForTA;
+ else if (UuidForRD != UuidForTA)
+ SeenMultipleGUIDs = true;
+ }
+
+ // Seeing multiple UUIDs means that we couldn't find a UUID
+ if (SeenMultipleGUIDs) {
+ if (RDHasMultipleGUIDsPtr)
+ *RDHasMultipleGUIDsPtr = true;
+ return 0;
+ }
+ }
+
+ return UuidForRD;
+ } else
+ for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(),
+ E = RD->redecls_end();
+ I != E; ++I)
+ if (UuidAttr *Uuid = I->getAttr<UuidAttr>())
+ return Uuid;
return 0;
}
OpenPOWER on IntegriCloud