diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index ba6c1d5f5c947..880e338224ddf 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2059,6 +2059,66 @@ bool ByteCodeExprGen::VisitExpressionTraitExpr( return this->emitConstBool(E->getValue(), E); } +template +bool ByteCodeExprGen::VisitCXXUuidofExpr(const CXXUuidofExpr *E) { + if (DiscardResult) + return true; + assert(!Initializing); + + std::optional GlobalIndex = P.getOrCreateGlobal(E->getGuidDecl()); + if (!GlobalIndex) + return false; + if (!this->emitGetPtrGlobal(*GlobalIndex, E)) + return false; + + const Record *R = this->getRecord(E->getType()); + assert(R); + + const APValue &V = E->getGuidDecl()->getAsAPValue(); + if (V.getKind() == APValue::None) + return true; + + assert(V.isStruct()); + assert(V.getStructNumBases() == 0); + // FIXME: This could be useful in visitAPValue, too. + for (unsigned I = 0, N = V.getStructNumFields(); I != N; ++I) { + const APValue &F = V.getStructField(I); + const Record::Field *RF = R->getField(I); + + if (F.isInt()) { + PrimType T = classifyPrim(RF->Decl->getType()); + if (!this->visitAPValue(F, T, E)) + return false; + if (!this->emitInitField(T, RF->Offset, E)) + return false; + } else if (F.isArray()) { + assert(RF->Desc->isPrimitiveArray()); + const auto *ArrType = RF->Decl->getType()->getAsArrayTypeUnsafe(); + PrimType ElemT = classifyPrim(ArrType->getElementType()); + assert(ArrType); + + if (!this->emitDupPtr(E)) + return false; + if (!this->emitGetPtrField(RF->Offset, E)) + return false; + + for (unsigned A = 0, AN = F.getArraySize(); A != AN; ++A) { + if (!this->visitAPValue(F.getArrayInitializedElt(A), ElemT, E)) + return false; + if (!this->emitInitElem(ElemT, A, E)) + return false; + } + + if (!this->emitPopPtr(E)) + return false; + } else { + assert(false && "I don't think this should be possible"); + } + } + + return this->emitInitPtr(E); +} + template bool ByteCodeExprGen::discard(const Expr *E) { if (E->containsErrors()) return false; diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index ae216f5671395..c723170110c55 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -113,6 +113,7 @@ class ByteCodeExprGen : public ConstStmtVisitor, bool>, bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E); bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E); + bool VisitCXXUuidofExpr(const CXXUuidofExpr *E); protected: bool visitExpr(const Expr *E) override; diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index b2b478af2e731..964c0377c6dc1 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -169,7 +169,7 @@ std::optional Program::createGlobal(const ValueDecl *VD, if (const auto *Var = dyn_cast(VD)) { IsStatic = Context::shouldBeGloballyIndexed(VD); IsExtern = !Var->getAnyInitializer(); - } else if (isa(VD)) { + } else if (isa(VD)) { IsStatic = true; IsExtern = false; } else { diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 9202bb98c822f..bc994c3191ce8 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -915,6 +915,13 @@ static_assert(ignoredDecls() == 12, ""); namespace DiscardExprs { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-value" + typedef struct _GUID { + __UINT32_TYPE__ Data1; + __UINT16_TYPE__ Data2; + __UINT16_TYPE__ Data3; + __UINT8_TYPE__ Data4[8]; + } GUID; + class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) GuidType; struct A{ int a; }; constexpr int ignoredExprs() { @@ -951,6 +958,8 @@ namespace DiscardExprs { (float)1; (double)1.0f; (signed)4u; + __uuidof(GuidType); + __uuidof(number); // both-error {{cannot call operator __uuidof on a type with no GUID}} return 0; } diff --git a/clang/test/SemaCXX/PR40395.cpp b/clang/test/SemaCXX/PR40395.cpp index 469c86d56209c..ea0fad2018771 100644 --- a/clang/test/SemaCXX/PR40395.cpp +++ b/clang/test/SemaCXX/PR40395.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++17 -fms-extensions -triple=x86_64-pc-win32 -verify %s +// RUN: %clang_cc1 -std=c++17 -fms-extensions -triple=x86_64-pc-win32 -verify %s -fexperimental-new-constant-interpreter // expected-no-diagnostics // PR40395 - ConstantExpr shouldn't cause the template object to infinitely diff --git a/clang/test/SemaCXX/ms-uuid.cpp b/clang/test/SemaCXX/ms-uuid.cpp index 21f93ecc3fa20..172e036e15f3f 100644 --- a/clang/test/SemaCXX/ms-uuid.cpp +++ b/clang/test/SemaCXX/ms-uuid.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations -fexperimental-new-constant-interpreter // RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -fms-extensions %s -Wno-deprecated-declarations +// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -fms-extensions %s -Wno-deprecated-declarations -fexperimental-new-constant-interpreter typedef struct _GUID { __UINT32_TYPE__ Data1;