zahiraam updated this revision to Diff 191371.
Herald added a subscriber: jdoerfert.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D43576/new/
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/ParsedAttr.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/Parser/MicrosoftExtensions.cpp
test/Parser/ms-square-bracket-attributes.mm
test/Sema/ms-uuid-1.cpp
utils/TableGen/ClangAttrEmitter.cpp
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,8 @@
Ptr = llvm::make_unique<VariadicIdentifierArgument>(Arg, Attr);
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/Sema/ms-uuid-1.cpp
===================================================================
--- /dev/null
+++ test/Sema/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: test/Parser/ms-square-bracket-attributes.mm
===================================================================
--- test/Parser/ms-square-bracket-attributes.mm
+++ test/Parser/ms-square-bracket-attributes.mm
@@ -19,7 +19,7 @@
// uuids must be ascii string literals.
// expected-error@+1 {{uuid attribute contains a malformed GUID}}
[uuid(u8"000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid_u8;
-// expected-error@+1 {{uuid attribute contains a malformed GUID}}
+// expected-error@+1 {{attribute requires a string}}
[uuid(L"000000A0-0000-0000-C000-000000000049")] struct struct_with_uuid_L;
// cl.exe doesn't allow raw string literals in []-style attributes, but does
Index: test/Parser/MicrosoftExtensions.cpp
===================================================================
--- test/Parser/MicrosoftExtensions.cpp
+++ test/Parser/MicrosoftExtensions.cpp
@@ -76,7 +76,7 @@
struct_with_uuid var_with_uuid[1];
struct_without_uuid var_without_uuid[1];
- __uuidof(struct_with_uuid);
+ __uuidof(struct_with_uuid); // expected-error {{non-type template argument of type 'const _GUID' is not a constant expression}}
__uuidof(struct_with_uuid2);
__uuidof(struct_with_uuid3);
__uuidof(struct_without_uuid); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
@@ -137,7 +137,7 @@
COM_CLASS_TEMPLATE_REF<int, __uuidof(struct_with_uuid)> good_template_arg;
-COM_CLASS_TEMPLATE<int, __uuidof(struct_with_uuid)> bad_template_arg; // expected-error {{non-type template argument of type 'const _GUID' is not a constant expression}}
+COM_CLASS_TEMPLATE<int, __uuidof(struct_with_uuid)> bad_template_arg;
namespace PR16911 {
struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid;
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: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -549,6 +549,16 @@
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
@@ -615,6 +615,43 @@
}
}
+/// Find the uuid of a type.
+static void FindStrUuid(Sema &SemaRef,
+ QualType QT,
+ llvm::SmallVector<const Decl *, 1> &UuidDecl) {
+ const Type *Ty = QT.getTypePtr();
+ const Decl *dcl;
+ if (QT->isPointerType() || QT->isReferenceType())
+ Ty = QT->getPointeeType().getTypePtr();
+ else if (QT->isArrayType())
+ Ty = Ty->getBaseElementTypeUnsafe();
+
+ const auto *TD = Ty->getAsTagDecl();
+ if (!TD) {
+ return;
+ }
+
+ dcl = TD->getMostRecentDecl();
+ if (TD->getMostRecentDecl()->getAttr<UuidAttr>()) {
+ const Decl *dl = SemaRef.DeclSpecUuidDecls.back();
+ UuidDecl.push_back(dcl);
+ return;
+ }
+
+ if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
+ const TemplateArgumentList &TAL = CTSD->getTemplateArgs();
+ for (const TemplateArgument &TA : TAL.asArray()) {
+ const Decl *dd = nullptr;
+ if (TA.getKind() == TemplateArgument::Type)
+ FindStrUuid(SemaRef, TA.getAsType(), UuidDecl);
+ else if (TA.getKind() == TemplateArgument::Declaration)
+ FindStrUuid(SemaRef, TA.getAsType(), UuidDecl);
+ if (dd)
+ UuidDecl.push_back(dcl);
+ }
+ }
+}
+
/// Build a Microsoft __uuidof expression with a type operand.
ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceLocation TypeidLoc,
@@ -622,17 +659,28 @@
SourceLocation RParenLoc) {
StringRef UuidStr;
if (!Operand->getType()->isDependentType()) {
- llvm::SmallSetVector<const UuidAttr *, 1> UuidAttrs;
- getUuidAttrOfType(*this, Operand->getType(), UuidAttrs);
- if (UuidAttrs.empty())
+ QualType QT = Operand->getType();
+ llvm::SmallVector<const Decl *, 1> UuidDecl;
+ FindStrUuid(*this, QT, UuidDecl);
+ if (UuidDecl.empty())
return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
- if (UuidAttrs.size() > 1)
+ if (UuidDecl.size() > 1)
return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids));
- UuidStr = UuidAttrs.back()->getGuid();
+ const Decl *dd1 = UuidDecl.back();
+ UuidStr = DeclSpecToStrUuid[dd1];
+ }
+
+ ExprResult expr = UuidExpMap[UuidStr];
+ ExprResult uuid_expr;
+ if (expr.isUnset()) {
+ uuid_expr =
+ new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, UuidStr,
+ SourceRange(TypeidLoc, RParenLoc));
+ UuidExpMap[UuidStr] = uuid_expr;
+ return uuid_expr;
+ } else {
+ return expr;
}
-
- return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, UuidStr,
- SourceRange(TypeidLoc, RParenLoc));
}
/// Build a Microsoft __uuidof expression with an expression operand.
@@ -651,7 +699,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
@@ -5365,9 +5365,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);
@@ -5386,14 +5387,27 @@
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);
@@ -5421,8 +5435,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(), StrRef);
+
+ S.DeclSpecUuidDecls.push_back(D);
+ S.DeclSpecToStrUuid[D] = StrRef;
+
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
@@ -2493,7 +2493,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 (const auto *SLHA = dyn_cast<SpeculativeLoadHardeningAttr>(Attr))
NewAttr = S.mergeSpeculativeLoadHardeningAttr(D, *SLHA);
else if (const auto *SLHA = dyn_cast<NoSpeculativeLoadHardeningAttr>(Attr))
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -585,6 +585,27 @@
ParsedAttr::AS_Declspec);
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, nullptr,
+ 0, ParsedAttr::AS_Declspec);
+ return true;
+ }
}
unsigned NumArgs =
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -106,6 +106,7 @@
case Decl::OMPCapturedExpr:
case Decl::OMPRequires:
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
@@ -1769,16 +1769,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 OMPThreadPrivate:
case OMPRequires:
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
@@ -4711,3 +4711,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
@@ -390,6 +390,14 @@
/// 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 is mapped to
+ /// a single Expr.
+ std::map<StringRef, ExprResult> UuidExpMap;
+ std::map<const Decl*, StringRef> DeclSpecToStrUuid;
+
/// pragma clang section kind
enum PragmaClangSectionKind {
PCSK_Invalid = 0,
@@ -2533,7 +2541,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/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'
@@ -216,6 +217,8 @@
const Expr *MessageExpr;
+ StringRef StrUuid;
+
ArgsUnion *getArgsBuffer() { return getTrailingObjects<ArgsUnion>(); }
ArgsUnion const *getArgsBuffer() const {
return getTrailingObjects<ArgsUnion>();
@@ -331,6 +334,16 @@
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
}
+ /// Constructor for __declspec(uuid) attribute.
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ StringRef struuid, ParsedAttr::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.
@@ -547,6 +560,11 @@
return getPropertyDataBuffer().SetterId;
}
+ 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.
@@ -782,6 +800,15 @@
return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
getterId, setterId, syntaxUsed));
}
+
+ ParsedAttr *
+ createUuidDeclSpecAttribute(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ StringRef struuid, ParsedAttr::Syntax syntaxUsed) {
+ void *memory = allocate(sizeof(ParsedAttr));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName,
+ scopeLoc, struuid, syntaxUsed));
+ }
};
class ParsedAttributesView {
@@ -974,6 +1001,16 @@
return attr;
}
+ /// Add microsoft __delspec(uuid) attribute.
+ ParsedAttr *
+ addNew(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName,
+ SourceLocation scopeLoc, StringRef struuid, ParsedAttr::Syntax syntaxUsed) {
+ ParsedAttr *attr =
+ pool.createUuidDeclSpecAttribute(attrName, attrRange, scopeName, scopeLoc,
+ struuid, syntaxUsed);
+ addAtEnd(attr);
+ return attr;
+ }
private:
mutable AttributePool pool;
};
Index: include/clang/Basic/DeclNodes.td
===================================================================
--- include/clang/Basic/DeclNodes.td
+++ include/clang/Basic/DeclNodes.td
@@ -100,4 +100,5 @@
def OMPThreadPrivate : Decl;
def OMPRequires : Decl;
def Empty : Decl;
+def DeclSpecUuid : Decl;
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -179,6 +179,8 @@
class VariadicStringArgument<string name> : Argument<name, 1>;
class VariadicIdentifierArgument<string name> : Argument<name, 1>;
+class DeclSpecUuidDeclArgument<string name, bit opt = 0> : Argument<name,opt>;
+
// Like VariadicUnsignedArgument except values are ParamIdx.
class VariadicParamIdxArgument<string name> : Argument<name, 1>;
@@ -2237,12 +2239,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
@@ -1428,6 +1428,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.
///
@@ -4269,6 +4270,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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits