Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -843,6 +843,10 @@ case TemplateArgument::Expression: return getDerived().TraverseStmt(Arg.getAsExpr()); + case TemplateArgument::UuidExpression: { + return getDerived().TraverseStmt(Arg.getAsUuidExpr()); + } + case TemplateArgument::Pack: return getDerived().TraverseTemplateArguments(Arg.pack_begin(), Arg.pack_size()); @@ -884,6 +888,10 @@ case TemplateArgument::Expression: return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); + case TemplateArgument::UuidExpression: { + return getDerived().TraverseStmt(ArgLoc.getSourceUuidExpression()); + } + case TemplateArgument::Pack: return getDerived().TraverseTemplateArguments(Arg.pack_begin(), Arg.pack_size()); Index: include/clang/AST/TemplateBase.h =================================================================== --- include/clang/AST/TemplateBase.h +++ include/clang/AST/TemplateBase.h @@ -43,6 +43,7 @@ class ASTContext; class DiagnosticBuilder; class Expr; +class CXXUuidofExpr; struct PrintingPolicy; class TypeSourceInfo; class ValueDecl; @@ -82,13 +83,15 @@ /// The template argument is an expression, and we've not resolved it to one /// of the other forms yet, either because it's dependent or because we're /// representing a non-canonical template argument (for instance, in a - /// TemplateSpecializationType). Also used to represent a non-dependent - /// __uuidof expression (a Microsoft extension). + /// TemplateSpecializationType). Expression, /// The template argument is actually a parameter pack. Arguments are stored /// in the Args struct. - Pack + Pack, + + /// The template argument is a uuid expression. This is a MS extension. + UuidExpression }; private: @@ -125,6 +128,12 @@ unsigned NumExpansions; void *Name; }; + struct UE { + unsigned Kind; + StringRef str; + QualType ty; + uintptr_t E; + }; struct TV { unsigned Kind; uintptr_t V; @@ -134,6 +143,7 @@ struct I Integer; struct A Args; struct TA TemplateArg; + struct UE UuidExpr; struct TV TypeOrValue; }; @@ -201,6 +211,7 @@ else TemplateArg.NumExpansions = 0; } + TemplateArgument(CXXUuidofExpr *E); /// \brief Construct a template argument that is an expression. /// @@ -332,6 +343,12 @@ return reinterpret_cast(TypeOrValue.V); } + /// \brief Retrieve the template argument as an uuid expression. + CXXUuidofExpr *getAsUuidExpr() const { + assert(getKind() == UuidExpression && "Unexpected kind"); + return reinterpret_cast(UuidExpr.E); + } + /// \brief Iterator that traverses the elements of a template argument pack. using pack_iterator = const TemplateArgument *; @@ -508,6 +525,11 @@ return LocInfo.getAsExpr(); } + Expr *getSourceUuidExpression() const { + assert(Argument.getKind() == TemplateArgument::UuidExpression); + return LocInfo.getAsExpr(); + } + Expr *getSourceDeclExpression() const { assert(Argument.getKind() == TemplateArgument::Declaration); return LocInfo.getAsExpr(); Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -5063,6 +5063,9 @@ case TemplateArgument::Expression: return Arg; + case TemplateArgument::UuidExpression: + return Arg; + case TemplateArgument::Declaration: { ValueDecl *D = cast(Arg.getAsDecl()->getCanonicalDecl()); return TemplateArgument(D, Arg.getParamTypeForDecl()); Index: lib/AST/ASTDumper.cpp =================================================================== --- lib/AST/ASTDumper.cpp +++ lib/AST/ASTDumper.cpp @@ -1002,6 +1002,10 @@ OS << " expr"; dumpStmt(A.getAsExpr()); break; + case TemplateArgument::UuidExpression: + OS << " uuidexpr"; + dumpStmt(A.getAsUuidExpr()); + break; case TemplateArgument::Pack: OS << " pack"; for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end(); Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -1284,6 +1284,11 @@ return TemplateArgument(ToExpr); return TemplateArgument(); + case TemplateArgument::UuidExpression: + if (Expr *ToExpr = Importer.Import(From.getAsUuidExpr())) + return TemplateArgument(ToExpr); + return TemplateArgument(); + case TemplateArgument::Pack: { SmallVector ToPack; ToPack.reserve(From.pack_size()); Index: lib/AST/ASTStructuralEquivalence.cpp =================================================================== --- lib/AST/ASTStructuralEquivalence.cpp +++ lib/AST/ASTStructuralEquivalence.cpp @@ -198,6 +198,10 @@ return IsStructurallyEquivalent(Context, Arg1.getAsExpr(), Arg2.getAsExpr()); + case TemplateArgument::UuidExpression: + return IsStructurallyEquivalent(Context, Arg1.getAsUuidExpr(), + Arg2.getAsExpr()); + case TemplateArgument::Pack: if (Arg1.pack_size() != Arg2.pack_size()) return false; Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -306,6 +306,7 @@ case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Expression: + case TemplateArgument::UuidExpression: continue; case TemplateArgument::Type: Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -1423,6 +1423,11 @@ case TemplateArgument::Expression: mangleExpression(TA.getAsExpr()); break; + case TemplateArgument::UuidExpression: { + const Expr *e = TA.getAsUuidExpr(); + mangleExpression(e); + break; + } case TemplateArgument::Pack: { ArrayRef TemplateArgs = TA.getPackAsArray(); if (TemplateArgs.empty()) { Index: lib/AST/ODRHash.cpp =================================================================== --- lib/AST/ODRHash.cpp +++ lib/AST/ODRHash.cpp @@ -149,6 +149,9 @@ case TemplateArgument::Expression: AddStmt(TA.getAsExpr()); break; + case TemplateArgument::UuidExpression: + AddStmt(TA.getAsUuidExpr()); + break; case TemplateArgument::Pack: ID.AddInteger(TA.pack_size()); for (auto SubTA : TA.pack_elements()) { Index: lib/AST/TemplateBase.cpp =================================================================== --- lib/AST/TemplateBase.cpp +++ lib/AST/TemplateBase.cpp @@ -103,6 +103,13 @@ Integer.Type = Type.getAsOpaquePtr(); } +TemplateArgument::TemplateArgument(CXXUuidofExpr *E) { + UuidExpr.Kind = UuidExpression; + UuidExpr.str = E->getUuidStr(); + UuidExpr.ty = E->getType(); + UuidExpr.E = reinterpret_cast(E); +} + TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context, ArrayRef Args) { @@ -148,6 +155,9 @@ if (P.isDependent()) return true; return false; + + case UuidExpression: + return (getAsUuidExpr()->isTypeDependent()); } llvm_unreachable("Invalid TemplateArgument Kind!"); @@ -179,6 +189,8 @@ // Never dependent return false; + case UuidExpression: + return getAsUuidExpr()->isInstantiationDependent(); case Expression: return getAsExpr()->isInstantiationDependent(); @@ -208,6 +220,9 @@ case Type: return isa(getAsType()); + case UuidExpression: + return isa(getAsUuidExpr()); + case Expression: return isa(getAsExpr()); } @@ -234,6 +249,11 @@ return true; break; + case UuidExpression: + if (getAsUuidExpr()->containsUnexpandedParameterPack()) + return true; + break; + case Expression: if (getAsExpr()->containsUnexpandedParameterPack()) return true; @@ -273,6 +293,9 @@ case TemplateArgument::Expression: return getAsExpr()->getType(); + case TemplateArgument::UuidExpression: + return getAsExpr()->getType(); + case TemplateArgument::Declaration: return getParamTypeForDecl(); @@ -333,6 +356,11 @@ ID.AddInteger(Args.NumArgs); for (unsigned I = 0; I != Args.NumArgs; ++I) Args.Args[I].Profile(ID, Context); + break; + + case UuidExpression: + UuidExpr.ty.Profile(ID); + break; } } @@ -348,6 +376,9 @@ case NullPtr: return TypeOrValue.V == Other.TypeOrValue.V; + case UuidExpression: + return UuidExpr.E == Other.UuidExpr.E; + case Declaration: return getAsDecl() == Other.getAsDecl(); @@ -373,6 +404,9 @@ case Type: return getAsType()->getAs()->getPattern(); + case UuidExpression: + return cast(getAsUuidExpr())->getPattern(); + case Expression: return cast(getAsExpr())->getPattern(); @@ -434,6 +468,10 @@ printIntegral(*this, Out, Policy); break; + case UuidExpression: + getAsUuidExpr()->printPretty(Out, nullptr, Policy); + break; + case Expression: getAsExpr()->printPretty(Out, nullptr, Policy); break; @@ -469,6 +507,7 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { switch (Argument.getKind()) { + case TemplateArgument::UuidExpression: case TemplateArgument::Expression: return getSourceExpression()->getSourceRange(); @@ -533,6 +572,16 @@ case TemplateArgument::TemplateExpansion: return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; + case TemplateArgument::UuidExpression: { + SmallString<32> Str; + llvm::raw_svector_ostream OS(Str); + LangOptions LangOpts; + LangOpts.CPlusPlus = true; + PrintingPolicy Policy(LangOpts); + Arg.getAsUuidExpr()->printPretty(OS, nullptr, Policy); + return DB << OS.str(); + } + case TemplateArgument::Expression: { // This shouldn't actually ever happen, so it's okay that we're // regurgitating an expression here. Index: lib/Sema/SemaLookup.cpp =================================================================== --- lib/Sema/SemaLookup.cpp +++ lib/Sema/SemaLookup.cpp @@ -2486,6 +2486,7 @@ case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::Expression: + case TemplateArgument::UuidExpression: case TemplateArgument::NullPtr: // [Note: non-type template arguments do not contribute to the set of // associated namespaces. ] Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -3395,6 +3395,15 @@ return NTTP && NTTP->getDepth() == Depth && NTTP->getIndex() == Index; } + case TemplateArgument::UuidExpression: { + DeclRefExpr *DRE = dyn_cast(Arg.getAsUuidExpr()); + if (!DRE || !DRE->getDecl()) + return false; + const NonTypeTemplateParmDecl *NTTP = + dyn_cast(DRE->getDecl()); + return NTTP && NTTP->getDepth() == Depth && NTTP->getIndex() == Index; + } + case TemplateArgument::Template: const TemplateTemplateParmDecl *TTP = dyn_cast_or_null( @@ -4614,6 +4623,25 @@ break; } + case TemplateArgument::UuidExpression: { + TemplateArgument Result; + ExprResult Res = + CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsUuidExpr(), + Result, CTAK); + if (Res.isInvalid()) + return true; + + // If the resulting expression is new, then use it in place of the + // old expression in the template argument. + if (Res.get() != Arg.getArgument().getAsUuidExpr()) { + TemplateArgument TA(Res.get()); + Arg = TemplateArgumentLoc(TA, Res.get()); + } + + Converted.push_back(Result); + break; + } + case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::NullPtr: @@ -4748,6 +4776,7 @@ Converted.push_back(Arg.getArgument()); break; + case TemplateArgument::UuidExpression: case TemplateArgument::Expression: case TemplateArgument::Type: // We have a template template parameter but the template @@ -5677,7 +5706,7 @@ ArgIn, Arg, ArgType)) return true; - Converted = TemplateArgument(ArgIn); + Converted = TemplateArgument(dyn_cast(Arg)); return false; } Index: lib/Sema/SemaTemplateDeduction.cpp =================================================================== --- lib/Sema/SemaTemplateDeduction.cpp +++ lib/Sema/SemaTemplateDeduction.cpp @@ -251,6 +251,20 @@ // Differing dependent expressions are incompatible. return DeducedTemplateArgument(); } + case TemplateArgument::UuidExpression: { + if (Y.getKind() != TemplateArgument::UuidExpression) + return checkDeducedTemplateArguments(Context, Y, X); + + // Compare the expressions for equality + llvm::FoldingSetNodeID ID1, ID2; + X.getAsUuidExpr()->Profile(ID1, Context, true); + Y.getAsUuidExpr()->Profile(ID2, Context, true); + if (ID1 == ID2) + return X.wasDeducedFromArrayBound() ? Y : X; + + // Differing dependent expressions are incompatible. + return DeducedTemplateArgument(); + } case TemplateArgument::Declaration: assert(!X.wasDeducedFromArrayBound()); @@ -2026,6 +2040,18 @@ // Can't deduce anything, but that's okay. return Sema::TDK_Success; } + case TemplateArgument::UuidExpression: { + if (NonTypeTemplateParmDecl *NTTP + = getDeducedParameterFromExpr(Info, Param.getAsUuidExpr())) { + if (Arg.getKind() == TemplateArgument::UuidExpression) + return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, + Arg.getAsExpr(), Info, Deduced); + + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + } + } case TemplateArgument::Pack: llvm_unreachable("Argument packs should be expanded by the caller!"); } @@ -2215,6 +2241,13 @@ return XID == YID; } + case TemplateArgument::UuidExpression: { + llvm::FoldingSetNodeID XID, YID; + X.getAsUuidExpr()->Profile(XID, Context, true); + Y.getAsUuidExpr()->Profile(YID, Context, true); + return XID == YID; + } + case TemplateArgument::Pack: if (X.pack_size() != Y.pack_size()) return false; @@ -2300,6 +2333,10 @@ case TemplateArgument::Expression: return TemplateArgumentLoc(Arg, Arg.getAsExpr()); + case TemplateArgument::UuidExpression: { + return TemplateArgumentLoc(Arg, Arg.getAsUuidExpr()); + } + case TemplateArgument::Pack: return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo()); } @@ -5390,6 +5427,13 @@ Depth, Used); break; + case TemplateArgument::UuidExpression: + { + MarkUsedTemplateParameters(Ctx, TemplateArg.getAsUuidExpr(), OnlyDeduced, + Depth, Used); + break; + } + case TemplateArgument::Pack: for (const auto &P : TemplateArg.pack_elements()) MarkUsedTemplateParameters(Ctx, P, OnlyDeduced, Depth, Used); Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -1257,7 +1257,11 @@ result = argExpr; type = argExpr->getType(); - } else if (arg.getKind() == TemplateArgument::Declaration || + } else if (arg.getKind() == TemplateArgument::UuidExpression) { + Expr *argExpr = arg.getAsUuidExpr(); + result = argExpr; + type = argExpr->getType(); + } else if (arg.getKind() == TemplateArgument::Declaration || arg.getKind() == TemplateArgument::NullPtr) { ValueDecl *VD; if (arg.getKind() == TemplateArgument::Declaration) { Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -3182,6 +3182,16 @@ return TemplateArgumentLoc(TemplateArgument(Expansion->getType()), Expansion); break; + + case TemplateArgument::UuidExpression: { + ExprResult Result + = getSema().CheckPackExpansion(Pattern.getSourceUuidExpression(), + EllipsisLoc, NumExpansions); + if (Result.isInvalid()) + return TemplateArgumentLoc(); + + return TemplateArgumentLoc(Result.get(), Result.get()); + } } return TemplateArgumentLoc(); @@ -3840,6 +3850,10 @@ case TemplateArgument::Expression: Output = TemplateArgumentLoc(Arg, Arg.getAsExpr()); break; + case TemplateArgument::UuidExpression: { + Output = TemplateArgumentLoc(Arg, Arg.getAsUuidExpr()); + break; + } case TemplateArgument::Declaration: case TemplateArgument::Integral: @@ -3915,6 +3929,22 @@ Output = TemplateArgumentLoc(TemplateArgument(E.get()), E.get()); return false; } + + case TemplateArgument::UuidExpression: { + EnterExpressionEvaluationContext Unevaluated( + getSema(), Uneval + ? Sema::ExpressionEvaluationContext::Unevaluated + : Sema::ExpressionEvaluationContext::ConstantEvaluated); + + Expr *InputExpr = Input.getSourceUuidExpression(); + if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); + + ExprResult E = getDerived().TransformExpr(InputExpr); + E = SemaRef.ActOnConstantExpression(E); + if (E.isInvalid()) return true; + Output = TemplateArgumentLoc(TemplateArgument(E.get()), E.get()); + return false; + } } // Work around bogus GCC warning Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -6936,6 +6936,8 @@ switch (Kind) { case TemplateArgument::Expression: return ReadExpr(F); + case TemplateArgument::UuidExpression: + return ReadExpr(F); case TemplateArgument::Type: return GetTypeSourceInfo(F, Record, Index); case TemplateArgument::Template: { @@ -8673,6 +8675,7 @@ NumTemplateExpansions = NumExpansions - 1; return TemplateArgument(Name, NumTemplateExpansions); } + case TemplateArgument::UuidExpression: case TemplateArgument::Expression: return TemplateArgument(ReadExpr(F)); case TemplateArgument::Pack: { Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -5408,6 +5408,9 @@ case TemplateArgument::Pack: // FIXME: Is this right? break; + case TemplateArgument::UuidExpression: + AddSourceLocation(Arg.getTemplateNameLoc()); + break; } } @@ -5866,6 +5869,9 @@ for (const auto &P : Arg.pack_elements()) AddTemplateArgument(P); break; + case TemplateArgument::UuidExpression: + AddTemplateName(Arg.getAsTemplateOrTemplatePattern()); + } } Index: test/Sema/member-reference-dll.cpp =================================================================== --- /dev/null +++ test/Sema/member-reference-dll.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fsyntax-only -verify -fms-extensions -fms-compatibility %s +// expected-no-diagnostics + +namespace test1 { +class __declspec(dllimport) Edge; + +template +class __declspec(dllimport) Range { + void insert(T *obj) { obj->loc(); } +}; + +template void Range::insert(Edge *); +} // namespace test1 + +namespace test2 { +class __declspec(dllexport) Edge; + +template +class __declspec(dllimport) Range { + void insert(T *obj) { obj->loc(); } +}; + +template void Range::insert(Edge *); +} // namespace test2 Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -1480,6 +1480,11 @@ return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest)); return false; + case TemplateArgument::UuidExpression: + if (Expr *E = TAL.getSourceUuidExpression()) + return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest)); + return false; + case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc()))