Index: include/clang/AST/Decl.h =================================================================== --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -75,6 +75,7 @@ class TypeLoc; class UnresolvedSetImpl; class VarTemplateDecl; +class DeclSpecUuidDecl; /// A container of type source information. /// @@ -4238,6 +4239,22 @@ static bool classofKind(Kind K) { return K == Empty; } }; +class DeclSpecUuidDecl : public Decl { + StringRef StrUuid; +public: + static DeclSpecUuidDecl *Create(const ASTContext &C, DeclContext *DC, + SourceLocation IdLoc, + StringRef UuidVal); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == DeclSpecUuid; } + + DeclSpecUuidDecl(Kind DK, DeclContext *DC, SourceLocation IdLoc, StringRef UuidVal) + : Decl (DK, DC, IdLoc), StrUuid(UuidVal) {} + + StringRef getStrUuid() { return StrUuid; } +}; + /// Insertion operator for diagnostics. This allows sending NamedDecl's /// into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -1416,6 +1416,8 @@ DEF_TRAVERSE_DECL(EmptyDecl, {}) +DEF_TRAVERSE_DECL(DeclSpecUuidDecl, {}) + DEF_TRAVERSE_DECL(FileScopeAsmDecl, { TRY_TO(TraverseStmt(D->getAsmString())); }) Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -172,6 +172,8 @@ // Like VariadicUnsignedArgument except values are ParamIdx. class VariadicParamIdxArgument : Argument; +class DeclSpecUuidDeclArgument : Argument; + // Like VariadicParamIdxArgument but for a single function parameter index. class ParamIdxArgument : Argument; @@ -2016,7 +2018,7 @@ def Uuid : InheritableAttr { let Spellings = [Declspec<"uuid">, Microsoft<"uuid">]; - let Args = [StringArgument<"Guid">]; + let Args = [DeclSpecUuidDeclArgument<"DeclSpecUuidDecl">]; let Subjects = SubjectList<[Record, Enum]>; // FIXME: Allow expressing logical AND for LangOpts. Our condition should be: // CPlusPlus && (MicrosoftExt || Borland) Index: include/clang/Basic/DeclNodes.td =================================================================== --- include/clang/Basic/DeclNodes.td +++ include/clang/Basic/DeclNodes.td @@ -98,4 +98,5 @@ def Import : Decl; def OMPThreadPrivate : Decl; def Empty : Decl; +def DeclSpecUuid : Decl; Index: include/clang/Sema/AttributeList.h =================================================================== --- include/clang/Sema/AttributeList.h +++ include/clang/Sema/AttributeList.h @@ -35,6 +35,7 @@ class Expr; class IdentifierInfo; class LangOptions; +class DeclSpecUuidDecl; /// \brief Represents information about a change in availability for /// an entity, which is part of the encoding of the 'availability' @@ -181,6 +182,8 @@ const Expr *MessageExpr; + DeclSpecUuidDecl *UuidDecl; + /// The next attribute in the current position. AttributeList *NextInPosition = nullptr; @@ -321,6 +324,16 @@ AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } + /// Constructor for __declspec(uuid) attribute. + AttributeList(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + DeclSpecUuidDecl *uuid, AttributeList::Syntax syntaxUsed) + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), Invalid(false), HasParsedType(false), + SyntaxUsed(syntaxUsed), NumArgs(1), UuidDecl(uuid) { + AttrKind = getKind(getName(), getScopeName(), syntaxUsed); + } + /// Type tag information is stored immediately following the arguments, if /// any, at the end of the object. They are mutually exclusive with /// availability slots. @@ -524,6 +537,11 @@ return getPropertyDataBuffer(); } + DeclSpecUuidDecl *getUuidDecl() const { + assert(getKind() == AT_Uuid && "Not an availability attribute"); + return UuidDecl; + } + /// \brief Get an index into the attribute spelling list /// defined in Attr.td. This index is used by an attribute /// to pretty print itself. @@ -577,6 +595,10 @@ 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*) }; @@ -744,6 +766,15 @@ getterId, setterId, syntaxUsed)); } + + AttributeList * + createUuidDeclSpecAttribute(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + DeclSpecUuidDecl *ArgDecl, AttributeList::Syntax syntaxUsed) { + void *memory = allocate(sizeof(AttributeList)); + return add(new (memory) AttributeList(attrName, attrRange, + scopeName, scopeLoc, ArgDecl, syntaxUsed)); + } }; /// ParsedAttributes - A collection of parsed attributes. Currently @@ -898,6 +929,18 @@ return attr; } + /// Add microsoft __delspec(uuid) attribute. + AttributeList * + addNew(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + DeclSpecUuidDecl *ArgDecl, AttributeList::Syntax syntaxUsed) { + AttributeList *attr = + pool.createUuidDeclSpecAttribute(attrName, attrRange, scopeName, + scopeLoc, ArgDecl, syntaxUsed); + add(attr); + return attr; + } + private: mutable AttributePool pool; AttributeList *list = nullptr; Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -2417,7 +2417,7 @@ VisibilityAttr::VisibilityType Vis, unsigned AttrSpellingListIndex); UuidAttr *mergeUuidAttr(Decl *D, SourceRange Range, - unsigned AttrSpellingListIndex, StringRef Uuid); + unsigned AttrSpellingListIndex, DeclSpecUuidDecl *Uuid); DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range, unsigned AttrSpellingListIndex); DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range, Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -4553,3 +4553,14 @@ ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) ExportDecl(nullptr, SourceLocation()); } + +//===----------------------------------------------------------------------===// +// UuidDeclSpec Implementation +//===----------------------------------------------------------------------===// + +DeclSpecUuidDecl * DeclSpecUuidDecl::Create(const ASTContext &C, DeclContext *DC, + SourceLocation IdLoc, + StringRef UuidVal) +{ + return new (C, DC) DeclSpecUuidDecl(DeclSpecUuid, DC, IdLoc, UuidVal); +} Index: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp +++ lib/AST/DeclBase.cpp @@ -810,6 +810,7 @@ case OMPThreadPrivate: case OMPCapturedExpr: case Empty: + case DeclSpecUuid: // Never looked up by name. return 0; } Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -1724,9 +1724,9 @@ if (Uuid && isStruct() && !getDeclContext()->isExternCContext() && !isDeclContextInNamespace(getDeclContext()) && ((getName() == "IUnknown" && - Uuid->getGuid() == "00000000-0000-0000-C000-000000000046") || + Uuid->getDeclSpecUuidDecl()->getStrUuid() == "00000000-0000-0000-C000-000000000046") || (getName() == "IDispatch" && - Uuid->getGuid() == "00020400-0000-0000-C000-000000000046"))) { + Uuid->getDeclSpecUuidDecl()->getStrUuid() == "00020400-0000-0000-C000-000000000046"))) { if (getNumBases() > 0) return false; return true; Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -556,7 +556,32 @@ T.skipToEnd(); return !HasInvalidAccessor; } - + if (AttrName->getName() == "uuid") { + // 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); + + // 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); + return true; + } unsigned NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr, SourceLocation(), AttributeList::AS_Declspec); @@ -911,6 +936,7 @@ enum { Introduced, Deprecated, Obsoleted, Unknown }; AvailabilityChange Changes[Unknown]; ExprResult MessageExpr, ReplacementExpr; + Decl *DeclSpecUuidDecl = nullptr; // Opening '('. BalancedDelimiterTracker T(*this, tok::l_paren); Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -2495,7 +2495,7 @@ NewAttr = nullptr; else if (const auto *UA = dyn_cast(Attr)) NewAttr = S.mergeUuidAttr(D, UA->getRange(), AttrSpellingListIndex, - UA->getGuid()); + UA->getDeclSpecUuidDecl()); else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr)) NewAttr = cast(Attr->clone(S.Context)); Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -4930,14 +4930,10 @@ //===----------------------------------------------------------------------===// UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range, - unsigned AttrSpellingListIndex, StringRef Uuid) { - if (const auto *UA = D->getAttr()) { - if (UA->getGuid().equals_lower(Uuid)) - return nullptr; - Diag(UA->getLocation(), diag::err_mismatched_uuid); - Diag(Range.getBegin(), diag::note_previous_uuid); - D->dropAttr(); - } + unsigned AttrSpellingListIndex, + DeclSpecUuidDecl *Uuid) { + if (D->getAttr()) + return nullptr; return ::new (Context) UuidAttr(Range, Context, Uuid, AttrSpellingListIndex); } @@ -4949,9 +4945,9 @@ return; } - StringRef StrRef; - SourceLocation LiteralLoc; - if (!S.checkStringLiteralArgumentAttr(AL, 0, StrRef, &LiteralLoc)) + StringRef StrRef = AL.getUuidDecl()->getStrUuid(); + SourceLocation LiteralLoc = AL.getLoc(); + if (StrRef.empty()) return; // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or @@ -4987,7 +4983,9 @@ S.Diag(AL.getLoc(), diag::warn_atl_uuid_deprecated); UuidAttr *UA = S.mergeUuidAttr(D, AL.getRange(), - AL.getAttributeSpellingListIndex(), StrRef); + AL.getAttributeSpellingListIndex(), + AL.getUuidDecl()); + if (UA) D->addAttr(UA); } Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -573,7 +573,7 @@ return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); if (UuidAttrs.size() > 1) return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); - UuidStr = UuidAttrs.back()->getGuid(); + UuidStr = UuidAttrs.back()->getDeclSpecUuidDecl()->getStrUuid(); } return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, UuidStr, @@ -596,7 +596,8 @@ return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); if (UuidAttrs.size() > 1) return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); - UuidStr = UuidAttrs.back()->getGuid(); + UuidStr = UuidAttrs.back()->getDeclSpecUuidDecl()->getStrUuid(); + } } Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -535,6 +535,15 @@ return Inst; } +Decl * +TemplateDeclInstantiator::VisitDeclSpecUuidDecl(DeclSpecUuidDecl *D) { + DeclSpecUuidDecl *Inst = DeclSpecUuidDecl::Create(SemaRef.Context, Owner, + D->getLocation(), + D->getStrUuid()); + Owner->addDecl(Inst); + return Inst; +} + Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias) { bool Invalid = false; Index: utils/TableGen/ClangAttrEmitter.cpp =================================================================== --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -322,12 +322,15 @@ OS << "\" << get" << getUpperName() << "().getAsString() << \""; else if (type == "ParamIdx") OS << "\" << get" << getUpperName() << "().getSourceIndex() << \""; - else + else if (type == "DeclSpecUuidDecl *") { + OS << "\" << get" << getUpperName() << "() << \""; + } else OS << "\" << get" << getUpperName() << "() << \""; } void writeDump(raw_ostream &OS) const override { - if (type == "FunctionDecl *" || type == "NamedDecl *") { + if (type == "FunctionDecl *" || type == "NamedDecl *" || + (type == "DeclSpecUuidDecl *")) { OS << " OS << \" \";\n"; OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n"; } else if (type == "IdentifierInfo *") { @@ -1280,6 +1283,8 @@ Ptr = llvm::make_unique(Arg, Attr, "ParamIdx"); else if (ArgName == "VersionArgument") Ptr = llvm::make_unique(Arg, Attr); + else if (ArgName == "DeclSpecUuidDeclArgument") + Ptr = llvm::make_unique(Arg, Attr, "DeclSpecUuidDecl *"); if (!Ptr) { // Search in reverse order so that the most-derived type is handled first.