diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 15c137098af35..e2fda18e3f44d 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1187,15 +1187,18 @@ inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) { /// 2) Pushes Pointer.atField(Off) on the stack inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) { const Pointer &Ptr = S.Stk.pop(); + if (S.inConstantContext() && !CheckNull(S, OpPC, Ptr, CSK_Field)) return false; - if (!CheckExtern(S, OpPC, Ptr)) - return false; - if (!CheckRange(S, OpPC, Ptr, CSK_Field)) - return false; - if (!CheckSubobject(S, OpPC, Ptr, CSK_Field)) - return false; + if (CheckDummy(S, OpPC, Ptr)) { + if (!CheckExtern(S, OpPC, Ptr)) + return false; + if (!CheckRange(S, OpPC, Ptr, CSK_Field)) + return false; + if (!CheckSubobject(S, OpPC, Ptr, CSK_Field)) + return false; + } S.Stk.push(Ptr.atField(Off)); return true; } @@ -1896,8 +1899,10 @@ inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) { inline bool ArrayDecay(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop(); - if (Ptr.isDummy()) - return false; + if (Ptr.isDummy()) { + S.Stk.push(Ptr); + return true; + } if (!Ptr.isUnknownSizeArray()) { S.Stk.push(Ptr.atIndex(0)); diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index 1eedbc360c157..d68af7922af5a 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -99,7 +99,7 @@ APValue Pointer::toAPValue() const { else llvm_unreachable("Invalid allocation type"); - if (isUnknownSizeArray() || Desc->asExpr()) + if (isDummy() || isUnknownSizeArray() || Desc->asExpr()) return APValue(Base, CharUnits::Zero(), Path, false, false); // TODO: compute the offset into the object. diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index afbc518e2af60..392b682afd602 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -112,3 +112,15 @@ _Static_assert(sizeof(name2) == 0, ""); // expected-error {{failed}} \ #ifdef __SIZEOF_INT128__ void *PR28739d = &(&PR28739d)[(__int128)(unsigned long)-1]; // all-warning {{refers past the last possible element}} #endif + +extern float global_float; +struct XX { int a, *b; }; +struct XY { int before; struct XX xx, *xp; float* after; } xy[] = { + 0, 0, &xy[0].xx.a, &xy[0].xx, &global_float, + [1].xx = 0, &xy[1].xx.a, &xy[1].xx, &global_float, + 0, // all-note {{previous initialization is here}} + 0, // all-note {{previous initialization is here}} + [2].before = 0, // all-warning {{initializer overrides prior initialization of this subobject}} + 0, // all-warning {{initializer overrides prior initialization of this subobject}} + &xy[2].xx.a, &xy[2].xx, &global_float +};