aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimm Bäder <tbaeder@redhat.com>2024-02-13 13:33:21 +0100
committerTimm Bäder <tbaeder@redhat.com>2024-02-13 13:41:06 +0100
commit9b718c0d5d0f1f146957753b7785f87f58cccfec (patch)
treef2896dd4324221954ed4915269b8629b1b3d2b8f
parent208edf7672cd2e84ae5da4df423adccd752ee1f1 (diff)
downloadllvm-9b718c0d5d0f1f146957753b7785f87f58cccfec.zip
llvm-9b718c0d5d0f1f146957753b7785f87f58cccfec.tar.gz
llvm-9b718c0d5d0f1f146957753b7785f87f58cccfec.tar.bz2
[clang][Interp] Handle CXXUuidofExprs
Allocate storage and initialize it with the given APValue contents.
-rw-r--r--clang/lib/AST/Interp/ByteCodeExprGen.cpp60
-rw-r--r--clang/lib/AST/Interp/ByteCodeExprGen.h1
-rw-r--r--clang/lib/AST/Interp/Program.cpp2
-rw-r--r--clang/test/AST/Interp/literals.cpp9
-rw-r--r--clang/test/SemaCXX/PR40395.cpp1
-rw-r--r--clang/test/SemaCXX/ms-uuid.cpp2
6 files changed, 74 insertions, 1 deletions
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index ba6c1d5..880e338 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2059,6 +2059,66 @@ bool ByteCodeExprGen<Emitter>::VisitExpressionTraitExpr(
return this->emitConstBool(E->getValue(), E);
}
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
+ if (DiscardResult)
+ return true;
+ assert(!Initializing);
+
+ std::optional<unsigned> 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 <class Emitter> bool ByteCodeExprGen<Emitter>::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 ae216f5..c723170 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -113,6 +113,7 @@ public:
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 b2b478a..964c037 100644
--- a/clang/lib/AST/Interp/Program.cpp
+++ b/clang/lib/AST/Interp/Program.cpp
@@ -169,7 +169,7 @@ std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
if (const auto *Var = dyn_cast<VarDecl>(VD)) {
IsStatic = Context::shouldBeGloballyIndexed(VD);
IsExtern = !Var->getAnyInitializer();
- } else if (isa<UnnamedGlobalConstantDecl>(VD)) {
+ } else if (isa<UnnamedGlobalConstantDecl, MSGuidDecl>(VD)) {
IsStatic = true;
IsExtern = false;
} else {
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 9202bb9..bc994c3 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 469c86d..ea0fad2 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 21f93ec..172e036 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;