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. /// @@ -4284,6 +4285,24 @@ static bool classofKind(Kind K) { return K == Empty; } }; +class DeclSpecUuidDecl : public Decl { + StringLiteral *STLUuid; +public: + static DeclSpecUuidDecl *Create(const ASTContext &C, DeclContext *DC, + SourceLocation IdLoc, + StringLiteral *stluuid); + + + 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, + StringLiteral *stluuid) + : Decl (DK, DC, IdLoc), STLUuid(stluuid) {} + + StringLiteral *getSTLUuid() { return STLUuid; } +}; + /// 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 @@ -1433,6 +1433,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 @@ -180,6 +180,7 @@ class VariadicExprArgument : Argument; class VariadicStringArgument : Argument; class VariadicIdentifierArgument : Argument; +class DeclSpecUuidDeclArgument : Argument; // Like VariadicUnsignedArgument except values are ParamIdx. class VariadicParamIdxArgument : Argument; @@ -2238,7 +2239,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 @@ -101,4 +101,5 @@ def OMPAllocate : Decl; def OMPRequires : Decl; def Empty : Decl; +def DeclSpecUuid : Decl; Index: include/clang/Sema/ParsedAttr.h =================================================================== --- include/clang/Sema/ParsedAttr.h +++ include/clang/Sema/ParsedAttr.h @@ -36,6 +36,7 @@ class Expr; class IdentifierInfo; class LangOptions; +class DeclSpecUuidDecl; /// Represents information about a change in availability for /// an entity, which is part of the encoding of the 'availability' @@ -333,6 +334,16 @@ AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } + /// Constructor for __declspec(uuid) attribute. + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + StringLiteral *stluuid, ParsedAttr::Syntax syntaxUsed) + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), Invalid(false), HasParsedType(false), + SyntaxUsed(syntaxUsed), NumArgs(1) { + 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. @@ -806,6 +817,15 @@ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, getterId, setterId, syntaxUsed)); } + + ParsedAttr * + createUuidDeclSpecAttribute(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + StringLiteral *stluuid, ParsedAttr::Syntax syntaxUsed) { + void *memory = allocate(sizeof(ParsedAttr)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, + scopeLoc, stluuid, syntaxUsed)); + } }; class ParsedAttributesView { @@ -905,6 +925,7 @@ /// is that this will become significantly more serious. class ParsedAttributes : public ParsedAttributesView { public: + ParsedAttributes(AttributeFactory &factory) : pool(factory) {} ParsedAttributes(const ParsedAttributes &) = delete; @@ -1005,6 +1026,17 @@ return attr; } + /// Add microsoft __delspec(uuid) attribute. + ParsedAttr * + addNew(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, + SourceLocation scopeLoc, StringLiteral *stluuid, ParsedAttr::Syntax syntaxUsed) { + ParsedAttr *attr = + pool.createUuidDeclSpecAttribute(attrName, attrRange, scopeName, scopeLoc, + stluuid, syntaxUsed); + addAtEnd(attr); + return attr; + } + private: mutable AttributePool pool; }; Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -405,6 +405,8 @@ /// Source location for newly created implicit MSInheritanceAttrs SourceLocation ImplicitMSInheritanceAttrLoc; + std::map DeclToDeclSpecUuidDecl; + /// pragma clang section kind enum PragmaClangSectionKind { PCSK_Invalid = 0, @@ -2578,7 +2580,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 @@ -4805,3 +4805,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, + StringLiteral *stluuid) { + return new (C, DC) DeclSpecUuidDecl(DeclSpecUuid, DC, IdLoc, stluuid); + } + Index: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp +++ lib/AST/DeclBase.cpp @@ -800,6 +800,7 @@ case OMPAllocate: case OMPRequires: case OMPCapturedExpr: + case DeclSpecUuid: case Empty: // Never looked up by name. return 0; Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -1793,9 +1793,11 @@ if (Uuid && isStruct() && !getDeclContext()->isExternCContext() && !isDeclContextInNamespace(getDeclContext()) && ((getName() == "IUnknown" && - Uuid->getGuid() == "00000000-0000-0000-C000-000000000046") || + Uuid->getDeclSpecUuidDecl()->getSTLUuid()->getString() == + "00000000-0000-0000-C000-000000000046") || (getName() == "IDispatch" && - Uuid->getGuid() == "00020400-0000-0000-C000-000000000046"))) { + Uuid->getDeclSpecUuidDecl()->getSTLUuid()->getString() == + "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 @@ -108,6 +108,7 @@ case Decl::OMPCapturedExpr: case Decl::OMPRequires: 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 @@ -1068,6 +1068,9 @@ FD->hasAttr()) MangledName = MangledName + ".stub"; + const auto ExistingRecord = Manglings.find(MangledName); + if (ExistingRecord != std::end(Manglings)) + Manglings.remove(&(*ExistingRecord)); auto Result = Manglings.insert(std::make_pair(MangledName, GD)); return MangledDeclNames[CanonicalGD] = Result.first->first(); } @@ -2999,7 +3002,6 @@ Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); setDSOLocal(Entry); } - // If there are two attempts to define the same mangled name, issue an // error. if (IsForDefinition && !Entry->isDeclaration()) { Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -2515,7 +2515,7 @@ NewAttr = nullptr; else if (const auto *UA = dyn_cast(Attr)) NewAttr = S.mergeUuidAttr(D, UA->getRange(), AttrSpellingListIndex, - UA->getGuid()); + UA->getDeclSpecUuidDecl()); else if (const auto *SLHA = dyn_cast(Attr)) NewAttr = S.mergeSpeculativeLoadHardeningAttr(D, *SLHA); else if (const auto *SLHA = dyn_cast(Attr)) Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -5399,9 +5399,12 @@ //===----------------------------------------------------------------------===// UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range, - unsigned AttrSpellingListIndex, StringRef Uuid) { - if (const auto *UA = D->getAttr()) { - if (UA->getGuid().equals_lower(Uuid)) + unsigned AttrSpellingListIndex, + DeclSpecUuidDecl *Uuid) { + if (auto *UA = D->getAttr()) { + if (UA->getDeclSpecUuidDecl()->getSTLUuid()->getString().equals_lower( + Uuid->getSTLUuid()->getString()) && + declaresSameEntity(DeclToDeclSpecUuidDecl.find(D)->first, D)) return nullptr; Diag(UA->getLocation(), diag::err_mismatched_uuid); Diag(Range.getBegin(), diag::note_previous_uuid); @@ -5446,6 +5449,16 @@ } } + QualType ResTy; + StringLiteral *Stl = nullptr; + llvm::APInt Length(32, StrRef.size() + 1); + ResTy = S.getASTContext().adjustStringLiteralBaseType( + S.getASTContext().WideCharTy.withConst()); + ResTy = S.getASTContext().getConstantArrayType(ResTy, Length, + ArrayType::Normal, 0); + Stl = StringLiteral::Create(S.getASTContext(), StrRef, StringLiteral::Ascii, + 0, ResTy, LiteralLoc); + // FIXME: It'd be nice to also emit a fixit removing uuid(...) (and, if it's // the only thing in the [] list, the [] too), and add an insertion of // __declspec(uuid(...)). But sadly, neither the SourceLocs of the commas @@ -5455,8 +5468,15 @@ if (AL.isMicrosoftAttribute()) // Check for [uuid(...)] spelling. S.Diag(AL.getLoc(), diag::warn_atl_uuid_deprecated); + DeclSpecUuidDecl *ArgDecl; + + ArgDecl = DeclSpecUuidDecl::Create(S.getASTContext(), S.getFunctionLevelDeclContext(), + SourceLocation(), Stl); + + S.DeclToDeclSpecUuidDecl[D] = ArgDecl; + UuidAttr *UA = S.mergeUuidAttr(D, AL.getRange(), - AL.getAttributeSpellingListIndex(), StrRef); + AL.getAttributeSpellingListIndex(), ArgDecl); if (UA) D->addAttr(UA); } Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -628,11 +628,12 @@ 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()->getSTLUuid()->getString(); } return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, UuidStr, SourceRange(TypeidLoc, RParenLoc)); + } /// Build a Microsoft __uuidof expression with an expression operand. @@ -651,7 +652,9 @@ 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()->getSTLUuid()->getString(); + if (UuidStr.startswith("{") && UuidStr.endswith("}")) + UuidStr = UuidStr.drop_front().drop_back(); } } Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -630,6 +630,11 @@ return Inst; } + Decl * + TemplateDeclInstantiator::VisitDeclSpecUuidDecl(DeclSpecUuidDecl *D) { + llvm_unreachable("DeclSpecUuidDecl cannot be instantiated"); +} + Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias) { bool Invalid = false; Index: lib/Serialization/ASTCommon.cpp =================================================================== --- lib/Serialization/ASTCommon.cpp +++ lib/Serialization/ASTCommon.cpp @@ -348,6 +348,7 @@ case Decl::ObjCProtocol: case Decl::ObjCInterface: case Decl::Empty: + case Decl::DeclSpecUuid: return true; // Never redeclarable. Index: test/Sema/ms-uuid-1.cpp =================================================================== --- /dev/null +++ test/Sema/ms-uuid-1.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions -fms-compatibility -std=c++14 %s +// expected-no-diagnostics +typedef struct _GUID { + int i; +} IID; +template +class A {}; + +struct + __declspec(uuid("{DDB47A6A-0F23-11D5-9109-00E0296B75D3}")) + S1 {}; + +struct + __declspec(uuid("{DDB47A6A-0F23-11D5-9109-00E0296B75D3}")) + S2 {}; + +struct __declspec(dllexport) + C1 : public A<&__uuidof(S1)> {}; + +struct __declspec(dllexport) + C2 : public A<&__uuidof(S2)> {}; +int printf(const char *, ...); +int main() { + + if (&__uuidof(S1) == &__uuidof(S2)) + printf("OK\n"); + else + printf("ERROR\n"); + + return 0; +} Index: test/Sema/ms-uuid-2.cpp =================================================================== --- /dev/null +++ test/Sema/ms-uuid-2.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions -fms-compatibility -std=c++14 %s + + +typedef struct _GUID +{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; + +// expected-error@+5 {{C++ requires a type specifier for all declarations}} +// expected-error@+4 {{invalid digit 'a' in decimal constant}} +// expected-error@+3 {{use of undeclared identifier 'def0'}} +// expected-error@+2 {{invalid digit 'a' in decimal constant}} +// expected-error@+1 {{expected ';' after top level declarator}} +uuid(12345678-9abc-def0-1234-56789abcdef0) struct S2; + Index: utils/TableGen/ClangAttrEmitter.cpp =================================================================== --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -321,12 +321,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 *") { @@ -1296,6 +1299,9 @@ Ptr = llvm::make_unique(Arg, Attr); 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.