summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/Decl.cpp
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2015-12-30 02:51:00 +0000
committerChandler Carruth <chandlerc@gmail.com>2015-12-30 02:51:00 +0000
commit813faed9200fd145f165baf4b620ceb356865786 (patch)
tree51ce52dc86178f80f621d06ea6396918599597be /clang/lib/AST/Decl.cpp
parent1d75c5eccf2846122776a9faafaa72aa57be9b3c (diff)
downloadbcm5719-llvm-813faed9200fd145f165baf4b620ceb356865786.tar.gz
bcm5719-llvm-813faed9200fd145f165baf4b620ceb356865786.zip
[ptr-traits] Stop using two bogus types as stand-ins for flags
indicating the nature of the default argument in a ParmVarDecl. Instead, this adds a proper enum stored exclusively in the ParmVarDecl bits (which we have plenty of) for this. This even allows us to track a previously unrepresented state in Clang when we parse a function declaration with a default argument on a parameter but we cannot even form an invalid expression node (for example, it is an invalid token). Now, we can model this state in the AST at least, and potentially improve recovery in this area in the future. I've also cleaned up the functions managing both variable initializer expressions and parameter default argument expresssions as much as possible. I've left some comments about further improvements based on a discussion with Richard Smith. Lots of credit to him for walking me through exactly which of the *many* tradeoffs here he felt was the best fit. Should be NFC for now. I've tried my best to preserve existing behavior. This is part of a series of patches to allow LLVM to check for complete pointee types when computing its pointer traits. This is absolutely necessary to get correct (or reproducible) results for things like how many low bits are guaranteed to be zero. llvm-svn: 256609
Diffstat (limited to 'clang/lib/AST/Decl.cpp')
-rw-r--r--clang/lib/AST/Decl.cpp91
1 files changed, 85 insertions, 6 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 9b43977b0bc..ff0b91001cc 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2031,6 +2031,31 @@ const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const {
return nullptr;
}
+bool VarDecl::hasInit() const {
+ if (auto *P = dyn_cast<ParmVarDecl>(this))
+ if (P->hasUnparsedDefaultArg() || P->hasUninstantiatedDefaultArg())
+ return false;
+
+ return !Init.isNull();
+}
+
+Expr *VarDecl::getInit() {
+ if (!hasInit())
+ return nullptr;
+
+ if (auto *S = Init.dyn_cast<Stmt *>())
+ return cast<Expr>(S);
+
+ return cast_or_null<Expr>(Init.get<EvaluatedStmt *>()->Value);
+}
+
+Stmt **VarDecl::getInitAddress() {
+ if (auto *ES = Init.dyn_cast<EvaluatedStmt *>())
+ return &ES->Value;
+
+ return Init.getAddrOfPtr1();
+}
+
bool VarDecl::isOutOfLine() const {
if (Decl::isOutOfLine())
return true;
@@ -2101,13 +2126,12 @@ bool VarDecl::isUsableInConstantExpressions(ASTContext &C) const {
EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const {
auto *Eval = Init.dyn_cast<EvaluatedStmt *>();
if (!Eval) {
- auto *S = Init.get<Stmt *>();
// Note: EvaluatedStmt contains an APValue, which usually holds
// resources not allocated from the ASTContext. We need to do some
// work to avoid leaking those, but we do so in VarDecl::evaluateValue
// where we can detect whether there's anything to clean up or not.
Eval = new (getASTContext()) EvaluatedStmt;
- Eval->Value = S;
+ Eval->Value = Init.get<Stmt *>();
Init = Eval;
}
return Eval;
@@ -2171,6 +2195,27 @@ APValue *VarDecl::evaluateValue(
return Result ? &Eval->Evaluated : nullptr;
}
+APValue *VarDecl::getEvaluatedValue() const {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+ if (Eval->WasEvaluated)
+ return &Eval->Evaluated;
+
+ return nullptr;
+}
+
+bool VarDecl::isInitKnownICE() const {
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+ return Eval->CheckedICE;
+
+ return false;
+}
+
+bool VarDecl::isInitICE() const {
+ assert(isInitKnownICE() &&
+ "Check whether we already know that the initializer is an ICE");
+ return Init.get<EvaluatedStmt *>()->IsICE;
+}
+
bool VarDecl::checkInitIsICE() const {
// Initializers of weak variables are never ICEs.
if (isWeak())
@@ -2336,14 +2381,48 @@ Expr *ParmVarDecl::getDefaultArg() {
return Arg;
}
+void ParmVarDecl::setDefaultArg(Expr *defarg) {
+ ParmVarDeclBits.DefaultArgKind = DAK_Normal;
+ Init = defarg;
+}
+
SourceRange ParmVarDecl::getDefaultArgRange() const {
- if (const Expr *E = getInit())
- return E->getSourceRange();
+ switch (ParmVarDeclBits.DefaultArgKind) {
+ case DAK_None:
+ case DAK_Unparsed:
+ // Nothing we can do here.
+ return SourceRange();
- if (hasUninstantiatedDefaultArg())
+ case DAK_Uninstantiated:
return getUninstantiatedDefaultArg()->getSourceRange();
- return SourceRange();
+ case DAK_Normal:
+ if (const Expr *E = getInit())
+ return E->getSourceRange();
+
+ // Missing an actual expression, may be invalid.
+ return SourceRange();
+ }
+ llvm_unreachable("Invalid default argument kind.");
+}
+
+void ParmVarDecl::setUninstantiatedDefaultArg(Expr *arg) {
+ ParmVarDeclBits.DefaultArgKind = DAK_Uninstantiated;
+ Init = arg;
+}
+
+Expr *ParmVarDecl::getUninstantiatedDefaultArg() {
+ assert(hasUninstantiatedDefaultArg() &&
+ "Wrong kind of initialization expression!");
+ return cast_or_null<Expr>(Init.get<Stmt *>());
+}
+
+bool ParmVarDecl::hasDefaultArg() const {
+ // FIXME: We should just return false for DAK_None here once callers are
+ // prepared for the case that we encountered an invalid default argument and
+ // were unable to even build an invalid expression.
+ return hasUnparsedDefaultArg() || hasUninstantiatedDefaultArg() ||
+ !Init.isNull();
}
bool ParmVarDecl::isParameterPack() const {
OpenPOWER on IntegriCloud