]> granicus.if.org Git - clang/commitdiff
In C++, an initializer on a variable doesn't necessarily mean it's the definition...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Mon, 1 Feb 2010 20:16:42 +0000 (20:16 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Mon, 1 Feb 2010 20:16:42 +0000 (20:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94999 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
lib/AST/Decl.cpp
lib/AST/Expr.cpp
lib/AST/ExprConstant.cpp
lib/CodeGen/CodeGenModule.cpp
lib/Sema/SemaChecking.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
tools/CIndex/CIndex.cpp

index 17ee3e54dadf3c863adf9bb5e453517443fedba2..dd83443c65f3fd6b3b03d4b862e33a7e7bb31b33 100644 (file)
@@ -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<VarDecl*>(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<VarDecl*>(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();
   }
index d75d355fdcf0da4e5069a5bcc70d2cd33267147b..894206a84716c6fe8c45d4d04a98c0085b64c2b6 100644 (file)
@@ -522,10 +522,6 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition() const {
   return Definition;
 }
 
-const VarDecl *VarDecl::getActingDefinition() const {
-  return const_cast<VarDecl*>(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;
+}
+
+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::getDefinition(const VarDecl *&Def) const {
+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;
index b76048a2b8d144cddb704bfa3f00c0d80b6193db..cf78c66a8d3ca06174e64ac1603c326930c575eb 100644 (file)
@@ -99,8 +99,7 @@ void DeclRefExpr::computeDependence() {
   else if (VarDecl *Var = dyn_cast<VarDecl>(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<DeclRefExpr>(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<DeclRefExpr>(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<DeclRefExpr>(E)->getLocation());
           }
index d64e6f1297d1e4735ba0cb61ae6d48f0c219af44..a0b2aa993faa746b4aab1d1a001e4c2e45939c54 100644 (file)
@@ -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<Expr *>(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<VarDecl>(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);
index 1773b41835e0e23d6f6db31565da7e3816e7302b..84a3c318e5204fd0dd9e27cc2fced4e309264a8f 100644 (file)
@@ -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
index 399979fc1ea1b701662a078005e10efe1ffd5b21..c6b826b32703de1e62259773eb383c23c407f2a3 100644 (file)
@@ -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);
       }
index a493a29a5d2304582edf5ad6a58e8ad8701ac27d..f9cbc930809a1e9e6120da6c41ef6f572d8c16f9 100644 (file)
@@ -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<VarDecl>(Previous.getFoundDecl());
-    if (PrevDecl && PrevDecl->getDefinition(Def) && D.hasAttributes()) {
+    VarDecl *Def = dyn_cast<VarDecl>(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);
index bba0e5d5f7fd972e061b7497bd209ced9148714a..745bd513a25a7f69ecbe871481ecb76698db1b34 100644 (file)
@@ -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);
index 5e97494dd9b955814156678fefced1c967130672..0bb862eb1a8c8bfcc6f00fa5200dcb4850f57a1d 100644 (file)
@@ -1733,23 +1733,10 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
   }
 
   case Decl::Var: {
-    VarDecl *Var = cast<VarDecl>(D);
-
-    // Variables with initializers have definitions.
-    const VarDecl *Def = 0;
-    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;
+    // Ask the variable if it has a definition.
+    if (VarDecl *Def = cast<VarDecl>(D)->getDefinition())
+      return MakeCXCursor(Def, CXXUnit);
+    return clang_getNullCursor();
   }
    
   case Decl::FunctionTemplate: {