diff options
author | David Majnemer <david.majnemer@gmail.com> | 2013-09-07 06:59:46 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2013-09-07 06:59:46 +0000 |
commit | 59c0ec23966acc3f6f2631b6cf09e56d2f2c2af0 (patch) | |
tree | 80e511242550c55e3c00d3da77a83da4a37ac49b /clang/lib/AST | |
parent | 76e98feb578c0cba1500554227699dafd9afe600 (diff) | |
download | bcm5719-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.cpp | 53 |
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; } |