Skip to content

Commit

Permalink
[clang][Interp] Handle CXXUuidofExprs
Browse files Browse the repository at this point in the history
Allocate storage and initialize it with the given APValue contents.
  • Loading branch information
tbaederr committed Feb 13, 2024
1 parent 208edf7 commit 9b718c0
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 1 deletion.
60 changes: 60 additions & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, 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;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 9 additions & 0 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaCXX/PR40395.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 2 additions & 0 deletions clang/test/SemaCXX/ms-uuid.cpp
Original file line number Diff line number Diff line change
@@ -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;
Expand Down

0 comments on commit 9b718c0

Please sign in to comment.