Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
clang/lib/AST/ExprConstant.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show All 37 Lines | |||||||||||
#include "clang/AST/APValue.h" | #include "clang/AST/APValue.h" | ||||||||||
#include "clang/AST/ASTContext.h" | #include "clang/AST/ASTContext.h" | ||||||||||
#include "clang/AST/ASTDiagnostic.h" | #include "clang/AST/ASTDiagnostic.h" | ||||||||||
#include "clang/AST/ASTLambda.h" | #include "clang/AST/ASTLambda.h" | ||||||||||
#include "clang/AST/Attr.h" | #include "clang/AST/Attr.h" | ||||||||||
#include "clang/AST/CXXInheritance.h" | #include "clang/AST/CXXInheritance.h" | ||||||||||
#include "clang/AST/CharUnits.h" | #include "clang/AST/CharUnits.h" | ||||||||||
#include "clang/AST/CurrentSourceLocExprScope.h" | #include "clang/AST/CurrentSourceLocExprScope.h" | ||||||||||
#include "clang/AST/DeclCXX.h" | |||||||||||
#include "clang/AST/Expr.h" | #include "clang/AST/Expr.h" | ||||||||||
#include "clang/AST/ExprCXX.h" | |||||||||||
#include "clang/AST/OSLog.h" | #include "clang/AST/OSLog.h" | ||||||||||
#include "clang/AST/OptionalDiagnostic.h" | #include "clang/AST/OptionalDiagnostic.h" | ||||||||||
#include "clang/AST/RecordLayout.h" | #include "clang/AST/RecordLayout.h" | ||||||||||
#include "clang/AST/StmtVisitor.h" | #include "clang/AST/StmtVisitor.h" | ||||||||||
#include "clang/AST/TypeLoc.h" | #include "clang/AST/TypeLoc.h" | ||||||||||
#include "clang/Basic/Builtins.h" | #include "clang/Basic/Builtins.h" | ||||||||||
#include "clang/Basic/TargetInfo.h" | #include "clang/Basic/TargetInfo.h" | ||||||||||
#include "llvm/ADT/APFixedPoint.h" | #include "llvm/ADT/APFixedPoint.h" | ||||||||||
▲ Show 20 Lines • Show All 866 Lines • ▼ Show 20 Lines | public: | ||||||||||
/// constant value. | /// constant value. | ||||||||||
bool InConstantContext; | bool InConstantContext; | ||||||||||
/// Whether we're checking that an expression is a potential constant | /// Whether we're checking that an expression is a potential constant | ||||||||||
/// expression. If so, do not fail on constructs that could become constant | /// expression. If so, do not fail on constructs that could become constant | ||||||||||
/// later on (such as a use of an undefined global). | /// later on (such as a use of an undefined global). | ||||||||||
bool CheckingPotentialConstantExpression = false; | bool CheckingPotentialConstantExpression = false; | ||||||||||
/// TODO: add doc. | |||||||||||
aaron.ballman: Add the docs? | |||||||||||
bool AccessingStaticConstantDataMember = false; | |||||||||||
/// Whether we're checking for an expression that has undefined behavior. | /// Whether we're checking for an expression that has undefined behavior. | ||||||||||
/// If so, we will produce warnings if we encounter an operation that is | /// If so, we will produce warnings if we encounter an operation that is | ||||||||||
/// always undefined. | /// always undefined. | ||||||||||
/// | /// | ||||||||||
/// Note that we still need to evaluate the expression normally when this | /// Note that we still need to evaluate the expression normally when this | ||||||||||
/// is set; this is used when evaluating ICEs in C. | /// is set; this is used when evaluating ICEs in C. | ||||||||||
bool CheckingForUndefinedBehavior = false; | bool CheckingForUndefinedBehavior = false; | ||||||||||
▲ Show 20 Lines • Show All 7,507 Lines • ▼ Show 20 Lines | bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { | ||||||||||
if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) { | if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) { | ||||||||||
VisitIgnoredBaseExpression(E->getBase()); | VisitIgnoredBaseExpression(E->getBase()); | ||||||||||
return VisitVarDecl(E, VD); | return VisitVarDecl(E, VD); | ||||||||||
} | } | ||||||||||
// Handle static member functions. | // Handle static member functions. | ||||||||||
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl())) { | if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl())) { | ||||||||||
if (MD->isStatic()) { | if (MD->isStatic()) { | ||||||||||
llvm::SaveAndRestore<bool> StaticMember( | |||||||||||
Info.AccessingStaticConstantDataMember); | |||||||||||
if(Info.InConstantContext) | |||||||||||
erichkeaneUnsubmitted Not Done ReplyInline ActionsWhen not in a constant-context, what should we be doing here? Why doesn't that set the variable? erichkeane: When not in a constant-context, what should we be doing here? Why doesn't that set the variable? | |||||||||||
Info.AccessingStaticConstantDataMember = true; | |||||||||||
VisitIgnoredBaseExpression(E->getBase()); | VisitIgnoredBaseExpression(E->getBase()); | ||||||||||
erichkeaneUnsubmitted Not Done ReplyInline ActionsWill this visit end up looking into OTHER things here? I guess I'm concerned about something like: this->get_some_other_type().static_func() and us skipping the this-> for THAT, despite it not being a static call in that context. erichkeane: Will this visit end up looking into OTHER things here? I guess I'm concerned about something… | |||||||||||
return Success(MD); | return Success(MD); | ||||||||||
} | } | ||||||||||
} | } | ||||||||||
// Handle non-static data members. | // Handle non-static data members. | ||||||||||
return LValueExprEvaluatorBaseTy::VisitMemberExpr(E); | return LValueExprEvaluatorBaseTy::VisitMemberExpr(E); | ||||||||||
} | } | ||||||||||
▲ Show 20 Lines • Show All 264 Lines • ▼ Show 20 Lines | if (!E->getBlockDecl()->hasCaptures()) | ||||||||||
return Success(E); | return Success(E); | ||||||||||
return Error(E); | return Error(E); | ||||||||||
} | } | ||||||||||
bool VisitCXXThisExpr(const CXXThisExpr *E) { | bool VisitCXXThisExpr(const CXXThisExpr *E) { | ||||||||||
// Can't look at 'this' when checking a potential constant expression. | // Can't look at 'this' when checking a potential constant expression. | ||||||||||
if (Info.checkingPotentialConstantExpression()) | if (Info.checkingPotentialConstantExpression()) | ||||||||||
return false; | return false; | ||||||||||
if (!Info.CurrentCall->This) { | if (!Info.CurrentCall->This) { | ||||||||||
if (Info.AccessingStaticConstantDataMember) { | |||||||||||
return Success(E); | |||||||||||
} | |||||||||||
aaron.ballmanUnsubmitted Not Done ReplyInline Actions
aaron.ballman: | |||||||||||
if (Info.getLangOpts().CPlusPlus11) | if (Info.getLangOpts().CPlusPlus11) | ||||||||||
Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit(); | Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit(); | ||||||||||
else | else | ||||||||||
Info.FFDiag(E); | Info.FFDiag(E); | ||||||||||
return false; | return false; | ||||||||||
} | } | ||||||||||
Result = *Info.CurrentCall->This; | Result = *Info.CurrentCall->This; | ||||||||||
// If we are inside a lambda's call operator, the 'this' expression refers | // If we are inside a lambda's call operator, the 'this' expression refers | ||||||||||
▲ Show 20 Lines • Show All 7,362 Lines • Show Last 20 Lines |
Add the docs?