aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/lib/AST/Interp/Interp.h21
-rw-r--r--clang/lib/AST/Interp/Pointer.cpp2
-rw-r--r--clang/test/AST/Interp/c.c12
3 files changed, 26 insertions, 9 deletions
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 15c1370..e2fda18e 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<Pointer>();
+
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<Pointer>(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<Pointer>();
- if (Ptr.isDummy())
- return false;
+ if (Ptr.isDummy()) {
+ S.Stk.push<Pointer>(Ptr);
+ return true;
+ }
if (!Ptr.isUnknownSizeArray()) {
S.Stk.push<Pointer>(Ptr.atIndex(0));
diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp
index 1eedbc3..d68af79 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 afbc518..392b682 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
+};