diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 17ee3e54dadf..dd83443c65f3 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -560,22 +560,19 @@ public: /// \brief Get the tentative definition that acts as the real definition in /// a TU. Returns null if there is a proper definition available. - const VarDecl *getActingDefinition() const; VarDecl *getActingDefinition(); + const VarDecl *getActingDefinition() const { + return const_cast(this)->getActingDefinition(); + } /// \brief Determine whether this is a tentative definition of a /// variable in C. bool isTentativeDefinitionNow() const; - /// \brief Retrieve the definition of this variable, which may come - /// from a previous declaration. Def will be set to the VarDecl that - /// contains the initializer, and the result will be that - /// initializer. - const Expr *getDefinition(const VarDecl *&Def) const; - - const Expr *getDefinition() const { - const VarDecl* Definition; - return getDefinition(Definition); + /// \brief Get the real (not just tentative) definition for this declaration. + VarDecl *getDefinition(); + const VarDecl *getDefinition() const { + return const_cast(this)->getDefinition(); } /// \brief Determine whether this is or was instantiated from an out-of-line @@ -600,6 +597,17 @@ public: 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 { return !Init.isNull(); } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index d75d355fdcf0..894206a84716 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -522,10 +522,6 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const { return Definition; } -const VarDecl *VarDecl::getActingDefinition() const { - return const_cast(this)->getActingDefinition(); -} - VarDecl *VarDecl::getActingDefinition() { DefinitionKind Kind = isThisDeclarationADefinition(); if (Kind != TentativeDefinition) @@ -553,16 +549,24 @@ bool VarDecl::isTentativeDefinitionNow() const { if ((*I)->isThisDeclarationADefinition() == Definition) 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(); while (I != E && !I->getInit()) ++I; if (I != E) { - Def = *I; + D = *I; return I->getInit(); } return 0; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index b76048a2b8d1..cf78c66a8d3c 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -99,8 +99,7 @@ void DeclRefExpr::computeDependence() { else if (VarDecl *Var = dyn_cast(D)) { if (Var->getType()->isIntegralType() && Var->getType().getCVRQualifiers() == Qualifiers::Const) { - const VarDecl *Def = 0; - if (const Expr *Init = Var->getDefinition(Def)) + if (const Expr *Init = Var->getAnyInitializer()) if (Init->isValueDependent()) ValueDependent = true; } @@ -1654,15 +1653,14 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { if (Quals.hasVolatile() || !Quals.hasConst()) return ICEDiag(2, cast(E)->getLocation()); - // Look for the definition of this variable, which will actually have - // an initializer. - const VarDecl *Def = 0; - const Expr *Init = Dcl->getDefinition(Def); + // Look for a declaration of this variable that has an initializer. + const VarDecl *ID = 0; + const Expr *Init = Dcl->getAnyInitializer(ID); if (Init) { - if (Def->isInitKnownICE()) { + if (ID->isInitKnownICE()) { // We have already checked whether this subexpression is an // integral constant expression. - if (Def->isInitICE()) + if (ID->isInitICE()) return NoDiag(); else return ICEDiag(2, cast(E)->getLocation()); @@ -1674,7 +1672,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // specify a constant-initializer which shall be an integral // constant expression (5.19). In that case, the member can appear // in integral constant expressions. - if (Def->isOutOfLine()) { + if (ID->isOutOfLine()) { Dcl->setInitKnownICE(false); return ICEDiag(2, cast(E)->getLocation()); } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index d64e6f1297d1..a0b2aa993faa 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -263,8 +263,7 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) { if (!VD->getType()->isReferenceType()) return APValue(E); // FIXME: Check whether VD might be overridden! - const VarDecl *Def = 0; - if (const Expr *Init = VD->getDefinition(Def)) + if (const Expr *Init = VD->getAnyInitializer()) return Visit(const_cast(Init)); } @@ -880,8 +879,7 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) { if (Info.Ctx.getCanonicalType(E->getType()).getCVRQualifiers() == Qualifiers::Const) { if (const VarDecl *VD = dyn_cast(D)) { - const VarDecl *Def = 0; - if (const Expr *Init = VD->getDefinition(Def)) { + if (const Expr *Init = VD->getAnyInitializer()) { if (APValue *V = VD->getEvaluatedValue()) { if (V->isInt()) return Success(V->getInt(), E); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 1773b41835e0..84a3c318e520 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -979,7 +979,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { QualType ASTTy = D->getType(); bool NonConstInit = false; - const Expr *InitExpr = D->getDefinition(); + const Expr *InitExpr = D->getAnyInitializer(); if (!InitExpr) { // This is a tentative definition; tentative definitions are diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 399979fc1ea1..c6b826b32703 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -846,8 +846,7 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, } if (isConstant) { - const VarDecl *Def = 0; - if (const Expr *Init = VD->getDefinition(Def)) + if (const Expr *Init = VD->getAnyInitializer()) return SemaCheckStringLiteral(Init, TheCall, HasVAListArg, format_idx, firstDataArg); } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a493a29a5d23..f9cbc930809a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2360,9 +2360,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, // attributes declared post-definition are currently ignored if (Previous.isSingleResult()) { - const VarDecl *Def = 0; - VarDecl *PrevDecl = dyn_cast(Previous.getFoundDecl()); - if (PrevDecl && PrevDecl->getDefinition(Def) && D.hasAttributes()) { + VarDecl *Def = dyn_cast(Previous.getFoundDecl()); + if (Def && (Def = Def->getDefinition()) && + Def != NewVD && D.hasAttributes()) { Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition); Diag(Def->getLocation(), diag::note_previous_definition); } @@ -3435,8 +3435,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { AbstractVariableType)) VDecl->setInvalidDecl(); - const VarDecl *Def = 0; - if (VDecl->getDefinition(Def)) { + const VarDecl *Def; + if ((Def = VDecl->getDefinition()) && Def != VDecl) { Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); Diag(Def->getLocation(), diag::note_previous_definition); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index bba0e5d5f7fd..745bd513a25a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4062,8 +4062,8 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, AbstractVariableType)) VDecl->setInvalidDecl(); - const VarDecl *Def = 0; - if (VDecl->getDefinition(Def)) { + const VarDecl *Def; + if ((Def = VDecl->getDefinition()) && Def != VDecl) { Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); Diag(Def->getLocation(), diag::note_previous_definition); diff --git a/clang/tools/CIndex/CIndex.cpp b/clang/tools/CIndex/CIndex.cpp index 5e97494dd9b9..0bb862eb1a8c 100644 --- a/clang/tools/CIndex/CIndex.cpp +++ b/clang/tools/CIndex/CIndex.cpp @@ -1733,23 +1733,10 @@ CXCursor clang_getCursorDefinition(CXCursor C) { } case Decl::Var: { - VarDecl *Var = cast(D); - - // Variables with initializers have definitions. - const VarDecl *Def = 0; - if (Var->getDefinition(Def)) - return MakeCXCursor(const_cast(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; + // Ask the variable if it has a definition. + if (VarDecl *Def = cast(D)->getDefinition()) + return MakeCXCursor(Def, CXXUnit); + return clang_getNullCursor(); } case Decl::FunctionTemplate: {