zahiraam updated this revision to Diff 146642. https://reviews.llvm.org/D43576
Files: include/clang/AST/Decl.h include/clang/AST/RecursiveASTVisitor.h include/clang/Basic/Attr.td include/clang/Basic/DeclNodes.td include/clang/Sema/AttributeList.h include/clang/Sema/Sema.h lib/AST/Decl.cpp lib/AST/DeclBase.cpp lib/AST/DeclCXX.cpp lib/CodeGen/CGDecl.cpp lib/Parse/ParseDecl.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Serialization/ASTCommon.cpp test/SemaCXX/ms-uuid-1.cpp utils/TableGen/ClangAttrEmitter.cpp
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<SimpleArgument>(Arg, Attr, "ParamIdx"); else if (ArgName == "VersionArgument") Ptr = llvm::make_unique<VersionArgument>(Arg, Attr); + else if (ArgName == "DeclSpecUuidDeclArgument") + Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "DeclSpecUuidDecl *"); if (!Ptr) { // Search in reverse order so that the most-derived type is handled first. Index: test/SemaCXX/ms-uuid-1.cpp =================================================================== --- /dev/null +++ test/SemaCXX/ms-uuid-1.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fms-extensions -fms-compatibility -std=c++14 -emit-obj -fdiagnostics-show-option %s +// expected-no-diagnostics +typedef struct _GUID { + int i; +} IID; +template <const IID *piid> +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: lib/Serialization/ASTCommon.cpp =================================================================== --- lib/Serialization/ASTCommon.cpp +++ lib/Serialization/ASTCommon.cpp @@ -272,6 +272,7 @@ case Decl::ObjCProtocol: case Decl::ObjCInterface: case Decl::Empty: + case Decl::DeclSpecUuid: return true; // Never redeclarable. 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: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -566,20 +566,66 @@ } } +/// Find the uuid of a type. +static void +FindStrUuid(Sema &SemaRef, QualType QT, + llvm::SmallVector<StringRef , 1> &StrUuid) { + const Type *Ty = QT.getTypePtr(); + if (QT->isPointerType() || QT->isReferenceType()) + Ty = QT->getPointeeType().getTypePtr(); + else if (QT->isArrayType()) + Ty = Ty->getBaseElementTypeUnsafe(); + + const auto *TD = Ty->getAsTagDecl(); + if (!TD) { + return; + } + const Decl* dd = + TD->getPreviousDecl() ? TD->getPreviousDecl() : + TD->getMostRecentDecl(); + auto str = SemaRef.DeclSpecToStrUuid.find(dd); + if (str != SemaRef.DeclSpecToStrUuid.end()) { + StrUuid.push_back(str->second); + return; + } + + if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) { + const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); + for (const TemplateArgument &TA : TAL.asArray()) { + if (TA.getKind() == TemplateArgument::Type) + FindStrUuid(SemaRef, TA.getAsType(), StrUuid); + else if (TA.getKind() == TemplateArgument::Declaration) + FindStrUuid(SemaRef, TA.getAsDecl()->getType(), StrUuid); + } + } +} + /// Build a Microsoft __uuidof expression with a type operand. ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, SourceLocation RParenLoc) { StringRef UuidStr; if (!Operand->getType()->isDependentType()) { - llvm::SmallSetVector<const UuidAttr *, 1> UuidAttrs; - getUuidAttrOfType(*this, Operand->getType(), UuidAttrs); - if (UuidAttrs.empty()) + auto B = StringRefToDecl.begin(); + if (StringRefToDecl.begin() == StringRefToDecl.end()) 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(); + llvm::SmallVector<StringRef, 1> UuidVec; + FindStrUuid(*this, Operand->getType(), UuidVec); + + if (UuidVec.empty()) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + UuidStr = UuidVec.back(); + auto expr = UuidExpMap.find(UuidStr); + Expr *uuid_exp; + if (expr == UuidExpMap.end()) { + uuid_exp = + new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, + UuidStr, SourceRange(TypeidLoc, RParenLoc)); + UuidExpMap[UuidStr] = (uuid_exp); + } else + uuid_exp = expr->second; + return uuid_exp; } return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, UuidStr, @@ -602,7 +648,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(); } } Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -4920,9 +4920,10 @@ //===----------------------------------------------------------------------===// UuidAttr *Sema::mergeUuidAttr(Decl *D, SourceRange Range, - unsigned AttrSpellingListIndex, StringRef Uuid) { - if (const auto *UA = D->getAttr<UuidAttr>()) { - if (UA->getGuid().equals_lower(Uuid)) + unsigned AttrSpellingListIndex, + DeclSpecUuidDecl *Uuid) { + if (auto *UA = D->getAttr<UuidAttr>()) { + if (UA->UuidAttr::getUuidAsStr().equals_lower(Uuid->getStrUuid())) return nullptr; Diag(UA->getLocation(), diag::err_mismatched_uuid); Diag(Range.getBegin(), diag::note_previous_uuid); @@ -4941,14 +4942,26 @@ StringRef StrRef; SourceLocation LiteralLoc; - if (!S.checkStringLiteralArgumentAttr(AL, 0, StrRef, &LiteralLoc)) - return; + StrRef = AL.getUuidStr(); + if (!StrRef.empty()) + LiteralLoc = AL.getLoc(); + else { + if (!S.checkStringLiteralArgumentAttr(AL, 0, StrRef, &LiteralLoc)) + return; + } // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former. if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}') StrRef = StrRef.drop_front().drop_back(); + // GUID string shouldn't be a wide string. + if (StrRef.front() == 'L') { + S.Diag(LiteralLoc, diag::err_attribute_argument_type) + << AL.getName() << AANT_ArgumentString; + return; + } + // Validate GUID length. if (StrRef.size() != 36) { S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); @@ -4976,8 +4989,20 @@ 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(), + StrRef); + + S.DeclSpecUuidDecls.push_back(D); + S.DeclSpecToStrUuid[D] = StrRef; + S.StringRefToDecl[StrRef] = S.DeclSpecUuidDecls; + UuidAttr *UA = S.mergeUuidAttr(D, AL.getRange(), - AL.getAttributeSpellingListIndex(), StrRef); + AL.getAttributeSpellingListIndex(), + ArgDecl); + if (UA) D->addAttr(UA); } Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -2489,7 +2489,7 @@ NewAttr = nullptr; else if (const auto *UA = dyn_cast<UuidAttr>(Attr)) NewAttr = S.mergeUuidAttr(D, UA->getRange(), AttrSpellingListIndex, - UA->getGuid()); + UA->getDeclSpecUuidDecl()); else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr)) NewAttr = cast<InheritableAttr>(Attr->clone(S.Context)); Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -555,6 +555,26 @@ T.skipToEnd(); return !HasInvalidAccessor; } + if (AttrName->getName() == "uuid") { + // Parse the uuid attribute and create a UuidDecl. + ConsumeParen(); + + 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('\"'); + + // 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, TrimmedUuidStr, AttributeList::AS_Declspec); + return true; + } unsigned NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr, 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/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -1721,16 +1721,16 @@ return false; // Check "Special" types. - const auto *Uuid = getAttr<UuidAttr>(); + auto *Uuid = getAttr<UuidAttr>(); // 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->getGuid() == "00000000-0000-0000-C000-000000000046") || + Uuid->UuidAttr::getUuidAsStr() == "00000000-0000-0000-C000-000000000046") || (getName() == "IDispatch" && - Uuid->getGuid() == "00020400-0000-0000-C000-000000000046"))) { + Uuid->UuidAttr::getUuidAsStr() == "00020400-0000-0000-C000-000000000046"))) { if (getNumBases() > 0) return false; return true; Index: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp +++ lib/AST/DeclBase.cpp @@ -814,6 +814,7 @@ case Import: case OMPThreadPrivate: case OMPCapturedExpr: + case DeclSpecUuid: case Empty: // Never looked up by name. return 0; Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -4562,3 +4562,13 @@ 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: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -349,6 +349,15 @@ /// Source location for newly created implicit MSInheritanceAttrs SourceLocation ImplicitMSInheritanceAttrLoc; + /// List of declspec(uuid ...) for a specific uuid string. + SmallVector<Decl *, 1> DeclSpecUuidDecls; + + /// Map from a uuid string to an expr. Each uuid string ismapped to + /// a single Expr. + std::map<StringRef, Expr*> UuidExpMap; + std::map<const Decl*, StringRef> DeclSpecToStrUuid; + std::map<StringRef, SmallVector<Decl *, 1>> StringRefToDecl; + /// pragma clang section kind enum PragmaClangSectionKind { PCSK_Invalid = 0, @@ -2416,7 +2425,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: 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; /// 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; + StringRef StrUuid; + /// 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, + StringRef struuid, AttributeList::Syntax syntaxUsed) + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), Invalid(false), HasParsedType(false), + SyntaxUsed(syntaxUsed), NumArgs(1), StrUuid(struuid) { + 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(); } + StringRef getUuidStr() const { + assert(getKind() == AT_Uuid && "Not an availability attribute"); + return StrUuid; + } + /// Get an index into the attribute spelling list /// defined in Attr.td. This index is used by an attribute /// to pretty print itself. @@ -744,6 +762,15 @@ getterId, setterId, syntaxUsed)); } + + AttributeList * + createUuidDeclSpecAttribute(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + StringRef struuid, AttributeList::Syntax syntaxUsed) { + void *memory = allocate(sizeof(AttributeList)); + return add(new (memory) AttributeList(attrName, attrRange, + scopeName, scopeLoc, struuid, syntaxUsed)); + } }; /// ParsedAttributes - A collection of parsed attributes. Currently @@ -898,6 +925,17 @@ return attr; } + /// Add microsoft __delspec(uuid) attribute. + AttributeList * + addNew(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + StringRef struuid, AttributeList::Syntax syntaxUsed) { + AttributeList *attr = + pool.createUuidDeclSpecAttribute(attrName, attrRange, scopeName, + scopeLoc, struuid, syntaxUsed); + add(attr); + return attr; + } private: mutable AttributePool pool; AttributeList *list = nullptr; Index: include/clang/Basic/DeclNodes.td =================================================================== --- include/clang/Basic/DeclNodes.td +++ include/clang/Basic/DeclNodes.td @@ -98,4 +98,4 @@ def Import : Decl; def OMPThreadPrivate : Decl; def Empty : Decl; - +def DeclSpecUuid : Decl; 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<string name> : Argument<name, 1>; +class DeclSpecUuidDeclArgument<string name, bit opt = 0> : Argument<name,opt>; + // Like VariadicParamIdxArgument but for a single function parameter index. class ParamIdxArgument<string name, bit opt = 0> : Argument<name, opt>; @@ -2027,12 +2029,15 @@ 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) let LangOpts = [MicrosoftExt, Borland]; let Documentation = [Undocumented]; + let AdditionalMembers = [{ + StringRef getUuidAsStr() { return getDeclSpecUuidDecl()->getStrUuid(); } + }]; } def VectorSize : TypeAttr { 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/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,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits