aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/Interp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode/Interp.cpp')
-rw-r--r--clang/lib/AST/ByteCode/Interp.cpp117
1 files changed, 63 insertions, 54 deletions
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 169a9a2..d640be0 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -832,6 +832,8 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false;
if (!CheckVolatile(S, OpPC, Ptr, AK))
return false;
+ if (!Ptr.isConst() && !S.inConstantContext() && isConstexprUnknown(Ptr))
+ return false;
return true;
}
@@ -868,7 +870,8 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return true;
}
-bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
+bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+ bool WillBeActivated) {
if (!Ptr.isBlockPointer() || Ptr.isZero())
return false;
@@ -883,7 +886,7 @@ bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return false;
if (!CheckRange(S, OpPC, Ptr, AK_Assign))
return false;
- if (!CheckActive(S, OpPC, Ptr, AK_Assign))
+ if (!WillBeActivated && !CheckActive(S, OpPC, Ptr, AK_Assign))
return false;
if (!CheckGlobal(S, OpPC, Ptr))
return false;
@@ -930,6 +933,15 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
if (F->isValid() && F->hasBody() && F->isConstexpr())
return true;
+ const FunctionDecl *DiagDecl = F->getDecl();
+ const FunctionDecl *Definition = nullptr;
+ DiagDecl->getBody(Definition);
+
+ if (!Definition && S.checkingPotentialConstantExpression() &&
+ DiagDecl->isConstexpr()) {
+ return false;
+ }
+
// Implicitly constexpr.
if (F->isLambdaStaticInvoker())
return true;
@@ -937,7 +949,7 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
// Bail out if the function declaration itself is invalid. We will
// have produced a relevant diagnostic while parsing it, so just
// note the problematic sub-expression.
- if (F->getDecl()->isInvalidDecl())
+ if (DiagDecl->isInvalidDecl())
return Invalid(S, OpPC);
// Diagnose failed assertions specially.
@@ -955,64 +967,61 @@ static bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
}
}
- if (S.getLangOpts().CPlusPlus11) {
- const FunctionDecl *DiagDecl = F->getDecl();
-
- // Invalid decls have been diagnosed before.
- if (DiagDecl->isInvalidDecl())
- return false;
+ if (!S.getLangOpts().CPlusPlus11) {
+ S.FFDiag(S.Current->getLocation(OpPC),
+ diag::note_invalid_subexpr_in_const_expr);
+ return false;
+ }
- // If this function is not constexpr because it is an inherited
- // non-constexpr constructor, diagnose that directly.
- const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
- if (CD && CD->isInheritingConstructor()) {
- const auto *Inherited = CD->getInheritedConstructor().getConstructor();
- if (!Inherited->isConstexpr())
- DiagDecl = CD = Inherited;
- }
+ // Invalid decls have been diagnosed before.
+ if (DiagDecl->isInvalidDecl())
+ return false;
- // Silently reject constructors of invalid classes. The invalid class
- // has been rejected elsewhere before.
- if (CD && CD->getParent()->isInvalidDecl())
- return false;
+ // If this function is not constexpr because it is an inherited
+ // non-constexpr constructor, diagnose that directly.
+ const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
+ if (CD && CD->isInheritingConstructor()) {
+ const auto *Inherited = CD->getInheritedConstructor().getConstructor();
+ if (!Inherited->isConstexpr())
+ DiagDecl = CD = Inherited;
+ }
- // FIXME: If DiagDecl is an implicitly-declared special member function
- // or an inheriting constructor, we should be much more explicit about why
- // it's not constexpr.
- if (CD && CD->isInheritingConstructor()) {
- S.FFDiag(S.Current->getLocation(OpPC),
- diag::note_constexpr_invalid_inhctor, 1)
- << CD->getInheritedConstructor().getConstructor()->getParent();
- S.Note(DiagDecl->getLocation(), diag::note_declared_at);
- } else {
- // Don't emit anything if the function isn't defined and we're checking
- // for a constant expression. It might be defined at the point we're
- // actually calling it.
- bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
- bool IsDefined = F->isDefined();
- if (!IsDefined && !IsExtern && DiagDecl->isConstexpr() &&
- S.checkingPotentialConstantExpression())
- return false;
+ // Silently reject constructors of invalid classes. The invalid class
+ // has been rejected elsewhere before.
+ if (CD && CD->getParent()->isInvalidDecl())
+ return false;
- // If the declaration is defined, declared 'constexpr' _and_ has a body,
- // the below diagnostic doesn't add anything useful.
- if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
- DiagDecl->hasBody())
- return false;
+ // FIXME: If DiagDecl is an implicitly-declared special member function
+ // or an inheriting constructor, we should be much more explicit about why
+ // it's not constexpr.
+ if (CD && CD->isInheritingConstructor()) {
+ S.FFDiag(S.Current->getLocation(OpPC), diag::note_constexpr_invalid_inhctor,
+ 1)
+ << CD->getInheritedConstructor().getConstructor()->getParent();
+ S.Note(DiagDecl->getLocation(), diag::note_declared_at);
+ } else {
+ // Don't emit anything if the function isn't defined and we're checking
+ // for a constant expression. It might be defined at the point we're
+ // actually calling it.
+ bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
+ bool IsDefined = F->isDefined();
+ if (!IsDefined && !IsExtern && DiagDecl->isConstexpr() &&
+ S.checkingPotentialConstantExpression())
+ return false;
- S.FFDiag(S.Current->getLocation(OpPC),
- diag::note_constexpr_invalid_function, 1)
- << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
+ // If the declaration is defined, declared 'constexpr' _and_ has a body,
+ // the below diagnostic doesn't add anything useful.
+ if (DiagDecl->isDefined() && DiagDecl->isConstexpr() && DiagDecl->hasBody())
+ return false;
- if (DiagDecl->getDefinition())
- S.Note(DiagDecl->getDefinition()->getLocation(),
- diag::note_declared_at);
- else
- S.Note(DiagDecl->getLocation(), diag::note_declared_at);
- }
- } else {
S.FFDiag(S.Current->getLocation(OpPC),
- diag::note_invalid_subexpr_in_const_expr);
+ diag::note_constexpr_invalid_function, 1)
+ << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
+
+ if (DiagDecl->getDefinition())
+ S.Note(DiagDecl->getDefinition()->getLocation(), diag::note_declared_at);
+ else
+ S.Note(DiagDecl->getLocation(), diag::note_declared_at);
}
return false;