Skip to content

Commit 9b718c0

Browse files
committed
[clang][Interp] Handle CXXUuidofExprs
Allocate storage and initialize it with the given APValue contents.
1 parent 208edf7 commit 9b718c0

File tree

6 files changed

+74
-1
lines changed

6 files changed

+74
-1
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2059,6 +2059,66 @@ bool ByteCodeExprGen<Emitter>::VisitExpressionTraitExpr(
20592059
return this->emitConstBool(E->getValue(), E);
20602060
}
20612061

2062+
template <class Emitter>
2063+
bool ByteCodeExprGen<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
2064+
if (DiscardResult)
2065+
return true;
2066+
assert(!Initializing);
2067+
2068+
std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(E->getGuidDecl());
2069+
if (!GlobalIndex)
2070+
return false;
2071+
if (!this->emitGetPtrGlobal(*GlobalIndex, E))
2072+
return false;
2073+
2074+
const Record *R = this->getRecord(E->getType());
2075+
assert(R);
2076+
2077+
const APValue &V = E->getGuidDecl()->getAsAPValue();
2078+
if (V.getKind() == APValue::None)
2079+
return true;
2080+
2081+
assert(V.isStruct());
2082+
assert(V.getStructNumBases() == 0);
2083+
// FIXME: This could be useful in visitAPValue, too.
2084+
for (unsigned I = 0, N = V.getStructNumFields(); I != N; ++I) {
2085+
const APValue &F = V.getStructField(I);
2086+
const Record::Field *RF = R->getField(I);
2087+
2088+
if (F.isInt()) {
2089+
PrimType T = classifyPrim(RF->Decl->getType());
2090+
if (!this->visitAPValue(F, T, E))
2091+
return false;
2092+
if (!this->emitInitField(T, RF->Offset, E))
2093+
return false;
2094+
} else if (F.isArray()) {
2095+
assert(RF->Desc->isPrimitiveArray());
2096+
const auto *ArrType = RF->Decl->getType()->getAsArrayTypeUnsafe();
2097+
PrimType ElemT = classifyPrim(ArrType->getElementType());
2098+
assert(ArrType);
2099+
2100+
if (!this->emitDupPtr(E))
2101+
return false;
2102+
if (!this->emitGetPtrField(RF->Offset, E))
2103+
return false;
2104+
2105+
for (unsigned A = 0, AN = F.getArraySize(); A != AN; ++A) {
2106+
if (!this->visitAPValue(F.getArrayInitializedElt(A), ElemT, E))
2107+
return false;
2108+
if (!this->emitInitElem(ElemT, A, E))
2109+
return false;
2110+
}
2111+
2112+
if (!this->emitPopPtr(E))
2113+
return false;
2114+
} else {
2115+
assert(false && "I don't think this should be possible");
2116+
}
2117+
}
2118+
2119+
return this->emitInitPtr(E);
2120+
}
2121+
20622122
template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
20632123
if (E->containsErrors())
20642124
return false;

clang/lib/AST/Interp/ByteCodeExprGen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
113113
bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E);
114114
bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E);
115115
bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E);
116+
bool VisitCXXUuidofExpr(const CXXUuidofExpr *E);
116117

117118
protected:
118119
bool visitExpr(const Expr *E) override;

clang/lib/AST/Interp/Program.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
169169
if (const auto *Var = dyn_cast<VarDecl>(VD)) {
170170
IsStatic = Context::shouldBeGloballyIndexed(VD);
171171
IsExtern = !Var->getAnyInitializer();
172-
} else if (isa<UnnamedGlobalConstantDecl>(VD)) {
172+
} else if (isa<UnnamedGlobalConstantDecl, MSGuidDecl>(VD)) {
173173
IsStatic = true;
174174
IsExtern = false;
175175
} else {

clang/test/AST/Interp/literals.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,13 @@ static_assert(ignoredDecls() == 12, "");
915915
namespace DiscardExprs {
916916
#pragma clang diagnostic push
917917
#pragma clang diagnostic ignored "-Wunused-value"
918+
typedef struct _GUID {
919+
__UINT32_TYPE__ Data1;
920+
__UINT16_TYPE__ Data2;
921+
__UINT16_TYPE__ Data3;
922+
__UINT8_TYPE__ Data4[8];
923+
} GUID;
924+
class __declspec(uuid("000000A0-0000-0000-C000-000000000049")) GuidType;
918925

919926
struct A{ int a; };
920927
constexpr int ignoredExprs() {
@@ -951,6 +958,8 @@ namespace DiscardExprs {
951958
(float)1;
952959
(double)1.0f;
953960
(signed)4u;
961+
__uuidof(GuidType);
962+
__uuidof(number); // both-error {{cannot call operator __uuidof on a type with no GUID}}
954963

955964
return 0;
956965
}

clang/test/SemaCXX/PR40395.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %clang_cc1 -std=c++17 -fms-extensions -triple=x86_64-pc-win32 -verify %s
2+
// RUN: %clang_cc1 -std=c++17 -fms-extensions -triple=x86_64-pc-win32 -verify %s -fexperimental-new-constant-interpreter
23
// expected-no-diagnostics
34

45
// PR40395 - ConstantExpr shouldn't cause the template object to infinitely

clang/test/SemaCXX/ms-uuid.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations
2+
// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -Wno-deprecated-declarations -fexperimental-new-constant-interpreter
23
// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -fms-extensions %s -Wno-deprecated-declarations
4+
// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify -fms-extensions %s -Wno-deprecated-declarations -fexperimental-new-constant-interpreter
35

46
typedef struct _GUID {
57
__UINT32_TYPE__ Data1;

0 commit comments

Comments
 (0)