Index: include/clang/AST/Decl.h =================================================================== --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -4240,7 +4240,10 @@ }; class DeclSpecUuidDecl : public Decl { +private: StringRef StrUuid; + DeclSpecUuidDecl *Next; + DeclSpecUuidDecl *Previous; public: static DeclSpecUuidDecl *Create(const ASTContext &C, DeclContext *DC, SourceLocation IdLoc, @@ -4250,9 +4253,13 @@ static bool classofKind(Kind K) { return K == DeclSpecUuid; } DeclSpecUuidDecl(Kind DK, DeclContext *DC, SourceLocation IdLoc, StringRef UuidVal) - : Decl (DK, DC, IdLoc), StrUuid(UuidVal) {} + : Decl (DK, DC, IdLoc), StrUuid(UuidVal), Next(nullptr), Previous(nullptr) {} StringRef getStrUuid() { return StrUuid; } + void setNext(DeclSpecUuidDecl *n) { Next = n; } + DeclSpecUuidDecl *getNext() { return Next; } + void setPrevious(DeclSpecUuidDecl *n) { Previous = n; } + DeclSpecUuidDecl *getPrevious() { return Previous; } }; /// Insertion operator for diagnostics. This allows sending NamedDecl's Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -2024,6 +2024,10 @@ // CPlusPlus && (MicrosoftExt || Borland) let LangOpts = [MicrosoftExt, Borland]; let Documentation = [Undocumented]; + let AdditionalMembers = [{ + StringRef getUuidAsStr() { return getDeclSpecUuidDecl()->getStrUuid(); } + }]; + } def VectorSize : TypeAttr { Index: include/clang/Sema/AttributeList.h =================================================================== --- include/clang/Sema/AttributeList.h +++ include/clang/Sema/AttributeList.h @@ -182,7 +182,7 @@ const Expr *MessageExpr; - DeclSpecUuidDecl *UuidDecl; + StringRef StrUuid; /// The next attribute in the current position. AttributeList *NextInPosition = nullptr; @@ -327,10 +327,10 @@ /// Constructor for __declspec(uuid) attribute. AttributeList(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - DeclSpecUuidDecl *uuid, AttributeList::Syntax syntaxUsed) + StringRef struuid, AttributeList::Syntax syntaxUsed) : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), ScopeLoc(scopeLoc), Invalid(false), HasParsedType(false), - SyntaxUsed(syntaxUsed), NumArgs(1), UuidDecl(uuid) { + SyntaxUsed(syntaxUsed), NumArgs(1), StrUuid(struuid) { AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -537,9 +537,9 @@ return getPropertyDataBuffer(); } - DeclSpecUuidDecl *getUuidDecl() const { - assert(getKind() == AT_Uuid && "Not an availability attribute"); - return UuidDecl; + StringRef getUuidStr() const { + assert(getKind() == AT_Uuid && "Not an availability attribute"); + return StrUuid; } /// \brief Get an index into the attribute spelling list @@ -595,10 +595,6 @@ PropertyAllocSize = sizeof(AttributeList) + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1) - / sizeof(void*) * sizeof(void*), - UuidDeclSpecSize = - sizeof(AttributeList) - + (sizeof(DeclSpecUuidDecl) + sizeof(void *) + sizeof(ArgsUnion) - 1) / sizeof(void*) * sizeof(void*) }; @@ -770,10 +766,10 @@ AttributeList * createUuidDeclSpecAttribute(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - DeclSpecUuidDecl *ArgDecl, AttributeList::Syntax syntaxUsed) { + StringRef struuid, AttributeList::Syntax syntaxUsed) { void *memory = allocate(sizeof(AttributeList)); return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, ArgDecl, syntaxUsed)); + scopeName, scopeLoc, struuid, syntaxUsed)); } }; @@ -933,10 +929,10 @@ AttributeList * addNew(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - DeclSpecUuidDecl *ArgDecl, AttributeList::Syntax syntaxUsed) { + StringRef struuid, AttributeList::Syntax syntaxUsed) { AttributeList *attr = pool.createUuidDeclSpecAttribute(attrName, attrRange, scopeName, - scopeLoc, ArgDecl, syntaxUsed); + scopeLoc, struuid, syntaxUsed); add(attr); return attr; } Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -350,6 +350,8 @@ /// \brief Source location for newly created implicit MSInheritanceAttrs SourceLocation ImplicitMSInheritanceAttrLoc; + std::map UuidDeclSpecMap; + /// \brief pragma clang section kind enum PragmaClangSectionKind { PCSK_Invalid = 0, Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -4558,9 +4558,8 @@ // UuidDeclSpec Implementation //===----------------------------------------------------------------------===// -DeclSpecUuidDecl * DeclSpecUuidDecl::Create(const ASTContext &C, DeclContext *DC, - SourceLocation IdLoc, - StringRef UuidVal) -{ +DeclSpecUuidDecl *DeclSpecUuidDecl::Create(const ASTContext &C, DeclContext *DC, + SourceLocation IdLoc, + StringRef UuidVal) { return new (C, DC) DeclSpecUuidDecl(DeclSpecUuid, DC, IdLoc, UuidVal); } Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -1717,16 +1717,16 @@ return false; // Check "Special" types. - const auto *Uuid = getAttr(); + auto *Uuid = getAttr(); // MS SDK declares IUnknown/IDispatch both in the root of a TU, or in an // extern C++ block directly in the TU. These are only valid if in one // of these two situations. if (Uuid && isStruct() && !getDeclContext()->isExternCContext() && !isDeclContextInNamespace(getDeclContext()) && ((getName() == "IUnknown" && - Uuid->getDeclSpecUuidDecl()->getStrUuid() == "00000000-0000-0000-C000-000000000046") || + Uuid->UuidAttr::getUuidAsStr() == "00000000-0000-0000-C000-000000000046") || (getName() == "IDispatch" && - Uuid->getDeclSpecUuidDecl()->getStrUuid() == "00020400-0000-0000-C000-000000000046"))) { + Uuid->UuidAttr::getUuidAsStr() == "00020400-0000-0000-C000-000000000046"))) { if (getNumBases() > 0) return false; return true; Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -105,6 +105,7 @@ case Decl::OMPThreadPrivate: case Decl::OMPCapturedExpr: case Decl::Empty: + case Decl::DeclSpecUuid: // None of these decls require codegen support. return; Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -982,7 +982,6 @@ if (FoundName != MangledDeclNames.end()) return FoundName->second; - // Keep the first result in the case of a mangling collision. const auto *ND = cast(GD.getDecl()); auto Result = Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -560,7 +560,6 @@ // Parse the uuid attribute and create a UuidDecl. ConsumeParen(); assert(Tok.is(tok::string_literal) && "uuid not followed by string literal '('"); - int sz = Tok.getLength(); SmallString<8> UuidBuffer; bool Invalid = false; StringRef UuidStr = PP.getSpelling(Tok, UuidBuffer, &Invalid); @@ -568,18 +567,13 @@ // Clean up the string from the "\" at begining and at end. StringRef UuidStr1 = UuidStr.ltrim('\"'); StringRef TrimmedUuidStr = UuidStr1.rtrim('\"'); - DeclSpecUuidDecl *ArgDecl = - DeclSpecUuidDecl::Create(Actions.getASTContext(), - Actions.getFunctionLevelDeclContext(), - SourceLocation(), - TrimmedUuidStr); // Advance to next token. Should be a r-paren. PP.Lex(Tok); SourceLocation RParen = Tok.getLocation(); SourceRange attrRange = SourceRange(AttrNameLoc, RParen); if (!ExpectAndConsume(tok::r_paren)) - Attrs.addNew(AttrName, attrRange, nullptr, AttrNameLoc, ArgDecl, AttributeList::AS_Declspec); + Attrs.addNew(AttrName, attrRange, nullptr, AttrNameLoc, TrimmedUuidStr, AttributeList::AS_Declspec); return true; } unsigned NumArgs = @@ -936,7 +930,6 @@ enum { Introduced, Deprecated, Obsoleted, Unknown }; AvailabilityChange Changes[Unknown]; ExprResult MessageExpr, ReplacementExpr; - Decl *DeclSpecUuidDecl = nullptr; // Opening '('. BalancedDelimiterTracker T(*this, tok::l_paren); Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -4932,8 +4932,13 @@ UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex, DeclSpecUuidDecl *Uuid) { - if (D->getAttr()) - return nullptr; + if (const auto *UA = D->getAttr()) { + if (UA->getDeclSpecUuidDecl()->getStrUuid().equals_lower(Uuid->getStrUuid())) + return nullptr; + Diag(UA->getLocation(), diag::err_mismatched_uuid); + Diag(Range.getBegin(), diag::note_previous_uuid); + D->dropAttr(); + } return ::new (Context) UuidAttr(Range, Context, Uuid, AttrSpellingListIndex); } @@ -4945,7 +4950,7 @@ return; } - StringRef StrRef = AL.getUuidDecl()->getStrUuid(); + StringRef StrRef = AL.getUuidStr(); SourceLocation LiteralLoc = AL.getLoc(); if (StrRef.empty()) return; @@ -4982,12 +4987,28 @@ if (AL.isMicrosoftAttribute()) // Check for [uuid(...)] spelling. S.Diag(AL.getLoc(), diag::warn_atl_uuid_deprecated); + DeclSpecUuidDecl *ArgDecl, *PreviousArgDecl; + ArgDecl = DeclSpecUuidDecl::Create(S.getASTContext(), + S.getFunctionLevelDeclContext(), + SourceLocation(), + StrRef); + + // Do a lookup of the declspec. + auto DSU = S.UuidDeclSpecMap.find(StrRef); + if (DSU != S.UuidDeclSpecMap.end()) { + PreviousArgDecl = DSU->second; + PreviousArgDecl->setNext(ArgDecl); + ArgDecl->setPrevious(PreviousArgDecl); + } + S.UuidDeclSpecMap[StrRef] = ArgDecl; + UuidAttr *UA = S.mergeUuidAttr(D, AL.getRange(), AL.getAttributeSpellingListIndex(), - AL.getUuidDecl()); + ArgDecl); if (UA) D->addAttr(UA); + } static void handleMSInheritanceAttr(Sema &S, Decl *D, const AttributeList &AL) { Index: lib/Serialization/ASTCommon.cpp =================================================================== --- lib/Serialization/ASTCommon.cpp +++ lib/Serialization/ASTCommon.cpp @@ -269,6 +269,7 @@ case Decl::ObjCProtocol: case Decl::ObjCInterface: case Decl::Empty: + case Decl::DeclSpecUuid: return true; // Never redeclarable. Index: utils/TableGen/ClangAttrEmitter.cpp =================================================================== --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -330,7 +330,7 @@ void writeDump(raw_ostream &OS) const override { if (type == "FunctionDecl *" || type == "NamedDecl *" || - (type == "DeclSpecUuidDecl *")) { + type == "DeclSpecUuidDecl *") { OS << " OS << \" \";\n"; OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n"; } else if (type == "IdentifierInfo *") {