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
  • [PATCH] D43576: S... Zahira Ammarguellat via Phabricator via cfe-commits
    • [PATCH] D435... Zahira Ammarguellat via Phabricator via cfe-commits
    • [PATCH] D435... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D435... Zahira Ammarguellat via Phabricator via cfe-commits
    • [PATCH] D435... Zahira Ammarguellat via Phabricator via cfe-commits
    • [PATCH] D435... Zahira Ammarguellat via Phabricator via cfe-commits
    • [PATCH] D435... Zahira Ammarguellat via Phabricator via cfe-commits
    • [PATCH] D435... Zahira Ammarguellat via Phabricator via cfe-commits

Reply via email to