In C++, an initializer on a variable doesn't necessarily mean it's the definition. With that in mind, rename getDefinition to getAnyInitializer (to distinguish it from getInit) and reimplement it in terms of isThisDeclarationADefinition. Update all code to use this new function.

llvm-svn: 94999
This commit is contained in:
Sebastian Redl 2010-02-01 20:16:42 +00:00
parent b18093e467
commit 5ca7984bb4
9 changed files with 51 additions and 57 deletions

View File

@ -560,22 +560,19 @@ public:
/// \brief Get the tentative definition that acts as the real definition in /// \brief Get the tentative definition that acts as the real definition in
/// a TU. Returns null if there is a proper definition available. /// a TU. Returns null if there is a proper definition available.
const VarDecl *getActingDefinition() const;
VarDecl *getActingDefinition(); VarDecl *getActingDefinition();
const VarDecl *getActingDefinition() const {
return const_cast<VarDecl*>(this)->getActingDefinition();
}
/// \brief Determine whether this is a tentative definition of a /// \brief Determine whether this is a tentative definition of a
/// variable in C. /// variable in C.
bool isTentativeDefinitionNow() const; bool isTentativeDefinitionNow() const;
/// \brief Retrieve the definition of this variable, which may come /// \brief Get the real (not just tentative) definition for this declaration.
/// from a previous declaration. Def will be set to the VarDecl that VarDecl *getDefinition();
/// contains the initializer, and the result will be that const VarDecl *getDefinition() const {
/// initializer. return const_cast<VarDecl*>(this)->getDefinition();
const Expr *getDefinition(const VarDecl *&Def) const;
const Expr *getDefinition() const {
const VarDecl* Definition;
return getDefinition(Definition);
} }
/// \brief Determine whether this is or was instantiated from an out-of-line /// \brief Determine whether this is or was instantiated from an out-of-line
@ -600,6 +597,17 @@ public:
return false; return false;
} }
/// getAnyInitializer - Get the initializer for this variable, no matter which
/// declaration it is attached to.
const Expr *getAnyInitializer() const {
const VarDecl *D;
return getAnyInitializer(D);
}
/// getAnyInitializer - Get the initializer for this variable, no matter which
/// declaration it is attached to. Also get that declaration.
const Expr *getAnyInitializer(const VarDecl *&D) const;
bool hasInit() const { bool hasInit() const {
return !Init.isNull(); return !Init.isNull();
} }

View File

@ -522,10 +522,6 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
return Definition; return Definition;
} }
const VarDecl *VarDecl::getActingDefinition() const {
return const_cast<VarDecl*>(this)->getActingDefinition();
}
VarDecl *VarDecl::getActingDefinition() { VarDecl *VarDecl::getActingDefinition() {
DefinitionKind Kind = isThisDeclarationADefinition(); DefinitionKind Kind = isThisDeclarationADefinition();
if (Kind != TentativeDefinition) if (Kind != TentativeDefinition)
@ -553,16 +549,24 @@ bool VarDecl::isTentativeDefinitionNow() const {
if ((*I)->isThisDeclarationADefinition() == Definition) if ((*I)->isThisDeclarationADefinition() == Definition)
return false; return false;
} }
return true; return true;
} }
const Expr *VarDecl::getDefinition(const VarDecl *&Def) const { VarDecl *VarDecl::getDefinition() {
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
if ((*I)->isThisDeclarationADefinition() == Definition)
return *I;
}
return 0;
}
const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const {
redecl_iterator I = redecls_begin(), E = redecls_end(); redecl_iterator I = redecls_begin(), E = redecls_end();
while (I != E && !I->getInit()) while (I != E && !I->getInit())
++I; ++I;
if (I != E) { if (I != E) {
Def = *I; D = *I;
return I->getInit(); return I->getInit();
} }
return 0; return 0;

View File

@ -99,8 +99,7 @@ void DeclRefExpr::computeDependence() {
else if (VarDecl *Var = dyn_cast<VarDecl>(D)) { else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
if (Var->getType()->isIntegralType() && if (Var->getType()->isIntegralType() &&
Var->getType().getCVRQualifiers() == Qualifiers::Const) { Var->getType().getCVRQualifiers() == Qualifiers::Const) {
const VarDecl *Def = 0; if (const Expr *Init = Var->getAnyInitializer())
if (const Expr *Init = Var->getDefinition(Def))
if (Init->isValueDependent()) if (Init->isValueDependent())
ValueDependent = true; ValueDependent = true;
} }
@ -1654,15 +1653,14 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
if (Quals.hasVolatile() || !Quals.hasConst()) if (Quals.hasVolatile() || !Quals.hasConst())
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
// Look for the definition of this variable, which will actually have // Look for a declaration of this variable that has an initializer.
// an initializer. const VarDecl *ID = 0;
const VarDecl *Def = 0; const Expr *Init = Dcl->getAnyInitializer(ID);
const Expr *Init = Dcl->getDefinition(Def);
if (Init) { if (Init) {
if (Def->isInitKnownICE()) { if (ID->isInitKnownICE()) {
// We have already checked whether this subexpression is an // We have already checked whether this subexpression is an
// integral constant expression. // integral constant expression.
if (Def->isInitICE()) if (ID->isInitICE())
return NoDiag(); return NoDiag();
else else
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
@ -1674,7 +1672,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
// specify a constant-initializer which shall be an integral // specify a constant-initializer which shall be an integral
// constant expression (5.19). In that case, the member can appear // constant expression (5.19). In that case, the member can appear
// in integral constant expressions. // in integral constant expressions.
if (Def->isOutOfLine()) { if (ID->isOutOfLine()) {
Dcl->setInitKnownICE(false); Dcl->setInitKnownICE(false);
return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation()); return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
} }

View File

@ -263,8 +263,7 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
if (!VD->getType()->isReferenceType()) if (!VD->getType()->isReferenceType())
return APValue(E); return APValue(E);
// FIXME: Check whether VD might be overridden! // FIXME: Check whether VD might be overridden!
const VarDecl *Def = 0; if (const Expr *Init = VD->getAnyInitializer())
if (const Expr *Init = VD->getDefinition(Def))
return Visit(const_cast<Expr *>(Init)); return Visit(const_cast<Expr *>(Init));
} }
@ -880,8 +879,7 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers() if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers()
== Qualifiers::Const) { == Qualifiers::Const) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
const VarDecl *Def = 0; if (const Expr *Init = VD->getAnyInitializer()) {
if (const Expr *Init = VD->getDefinition(Def)) {
if (APValue *V = VD->getEvaluatedValue()) { if (APValue *V = VD->getEvaluatedValue()) {
if (V->isInt()) if (V->isInt())
return Success(V->getInt(), E); return Success(V->getInt(), E);

View File

@ -979,7 +979,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
QualType ASTTy = D->getType(); QualType ASTTy = D->getType();
bool NonConstInit = false; bool NonConstInit = false;
const Expr *InitExpr = D->getDefinition(); const Expr *InitExpr = D->getAnyInitializer();
if (!InitExpr) { if (!InitExpr) {
// This is a tentative definition; tentative definitions are // This is a tentative definition; tentative definitions are

View File

@ -846,8 +846,7 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
} }
if (isConstant) { if (isConstant) {
const VarDecl *Def = 0; if (const Expr *Init = VD->getAnyInitializer())
if (const Expr *Init = VD->getDefinition(Def))
return SemaCheckStringLiteral(Init, TheCall, return SemaCheckStringLiteral(Init, TheCall,
HasVAListArg, format_idx, firstDataArg); HasVAListArg, format_idx, firstDataArg);
} }

View File

@ -2360,9 +2360,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// attributes declared post-definition are currently ignored // attributes declared post-definition are currently ignored
if (Previous.isSingleResult()) { if (Previous.isSingleResult()) {
const VarDecl *Def = 0; VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl());
VarDecl *PrevDecl = dyn_cast<VarDecl>(Previous.getFoundDecl()); if (Def && (Def = Def->getDefinition()) &&
if (PrevDecl && PrevDecl->getDefinition(Def) && D.hasAttributes()) { Def != NewVD && D.hasAttributes()) {
Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition); Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition);
Diag(Def->getLocation(), diag::note_previous_definition); Diag(Def->getLocation(), diag::note_previous_definition);
} }
@ -3435,8 +3435,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
AbstractVariableType)) AbstractVariableType))
VDecl->setInvalidDecl(); VDecl->setInvalidDecl();
const VarDecl *Def = 0; const VarDecl *Def;
if (VDecl->getDefinition(Def)) { if ((Def = VDecl->getDefinition()) && Def != VDecl) {
Diag(VDecl->getLocation(), diag::err_redefinition) Diag(VDecl->getLocation(), diag::err_redefinition)
<< VDecl->getDeclName(); << VDecl->getDeclName();
Diag(Def->getLocation(), diag::note_previous_definition); Diag(Def->getLocation(), diag::note_previous_definition);

View File

@ -4062,8 +4062,8 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
AbstractVariableType)) AbstractVariableType))
VDecl->setInvalidDecl(); VDecl->setInvalidDecl();
const VarDecl *Def = 0; const VarDecl *Def;
if (VDecl->getDefinition(Def)) { if ((Def = VDecl->getDefinition()) && Def != VDecl) {
Diag(VDecl->getLocation(), diag::err_redefinition) Diag(VDecl->getLocation(), diag::err_redefinition)
<< VDecl->getDeclName(); << VDecl->getDeclName();
Diag(Def->getLocation(), diag::note_previous_definition); Diag(Def->getLocation(), diag::note_previous_definition);

View File

@ -1733,23 +1733,10 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
} }
case Decl::Var: { case Decl::Var: {
VarDecl *Var = cast<VarDecl>(D); // Ask the variable if it has a definition.
if (VarDecl *Def = cast<VarDecl>(D)->getDefinition())
// Variables with initializers have definitions. return MakeCXCursor(Def, CXXUnit);
const VarDecl *Def = 0; return clang_getNullCursor();
if (Var->getDefinition(Def))
return MakeCXCursor(const_cast<VarDecl *>(Def), CXXUnit);
// extern and private_extern variables are not definitions.
if (Var->hasExternalStorage())
return clang_getNullCursor();
// In-line static data members do not have definitions.
if (Var->isStaticDataMember() && !Var->isOutOfLine())
return clang_getNullCursor();
// All other variables are themselves definitions.
return C;
} }
case Decl::FunctionTemplate: { case Decl::FunctionTemplate: {