[cfe-commits] r152761 - /cfe/trunk/lib/AST/ExprConstant.cpp

Richard Smith richard-llvm at metafoo.co.uk
Wed Mar 14 17:41:49 PDT 2012


Author: rsmith
Date: Wed Mar 14 19:41:48 2012
New Revision: 152761

URL: http://llvm.org/viewvc/llvm-project?rev=152761&view=rev
Log:
Minor optimization to constant evaluation: don't bother computing expr source
locations for diagnostics we're not going to emit, and don't track the subobject
designator outside C++11 (since we're not going to use it anyway).

This seems to give about a 0.5% speedup on 403.gcc/combine.c, but the results
were sufficiently noisy that I can't reject the null hypothesis.

Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=152761&r1=152760&r2=152761&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Mar 14 19:41:48 2012
@@ -480,9 +480,18 @@
       return OptionalDiagnostic();
     }
 
+    OptionalDiagnostic Diag(const Expr *E, diag::kind DiagId
+                              = diag::note_invalid_subexpr_in_const_expr,
+                            unsigned ExtraNotes = 0) {
+      if (EvalStatus.Diag)
+        return Diag(E->getExprLoc(), DiagId, ExtraNotes);
+      return OptionalDiagnostic();
+    }
+
     /// Diagnose that the evaluation does not produce a C++11 core constant
     /// expression.
-    OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId
+    template<typename LocArg>
+    OptionalDiagnostic CCEDiag(LocArg Loc, diag::kind DiagId
                                  = diag::note_invalid_subexpr_in_const_expr,
                                unsigned ExtraNotes = 0) {
       // Don't override a previous diagnostic.
@@ -556,7 +565,7 @@
   if (Invalid)
     return false;
   if (isOnePastTheEnd()) {
-    Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_past_end_subobject)
+    Info.CCEDiag(E, diag::note_constexpr_past_end_subobject)
       << CSK;
     setInvalid();
     return false;
@@ -567,11 +576,11 @@
 void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info,
                                                     const Expr *E, uint64_t N) {
   if (MostDerivedPathLength == Entries.size() && MostDerivedArraySize)
-    Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_array_index)
+    Info.CCEDiag(E, diag::note_constexpr_array_index)
       << static_cast<int>(N) << /*array*/ 0
       << static_cast<unsigned>(MostDerivedArraySize);
   else
-    Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_array_index)
+    Info.CCEDiag(E, diag::note_constexpr_array_index)
       << static_cast<int>(N) << /*non-array*/ 1;
   setInvalid();
 }
@@ -730,7 +739,7 @@
       if (Designator.Invalid)
         return false;
       if (!Base) {
-        Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_null_subobject)
+        Info.CCEDiag(E, diag::note_constexpr_null_subobject)
           << CSK;
         Designator.setInvalid();
         return false;
@@ -741,27 +750,30 @@
     // Check this LValue refers to an object. If not, set the designator to be
     // invalid and emit a diagnostic.
     bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) {
+      // Outside C++11, do not build a designator referring to a subobject of
+      // any object: we won't use such a designator for anything.
+      if (!Info.getLangOpts().CPlusPlus0x)
+        Designator.setInvalid();
       return checkNullPointer(Info, E, CSK) &&
              Designator.checkSubobject(Info, E, CSK);
     }
 
     void addDecl(EvalInfo &Info, const Expr *E,
                  const Decl *D, bool Virtual = false) {
-      checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base);
-      Designator.addDeclUnchecked(D, Virtual);
+      if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base))
+        Designator.addDeclUnchecked(D, Virtual);
     }
     void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) {
-      checkSubobject(Info, E, CSK_ArrayToPointer);
-      Designator.addArrayUnchecked(CAT);
+      if (checkSubobject(Info, E, CSK_ArrayToPointer))
+        Designator.addArrayUnchecked(CAT);
     }
     void addComplex(EvalInfo &Info, const Expr *E, QualType EltTy, bool Imag) {
-      checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real);
-      Designator.addComplexUnchecked(EltTy, Imag);
+      if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real))
+        Designator.addComplexUnchecked(EltTy, Imag);
     }
     void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) {
-      if (!checkNullPointer(Info, E, CSK_ArrayIndex))
-        return;
-      Designator.adjustIndex(Info, E, N);
+      if (checkNullPointer(Info, E, CSK_ArrayIndex))
+        Designator.adjustIndex(Info, E, N);
     }
   };
 
@@ -1020,10 +1032,10 @@
 
   // Prvalue constant expressions must be of literal types.
   if (Info.getLangOpts().CPlusPlus0x)
-    Info.Diag(E->getExprLoc(), diag::note_constexpr_nonliteral)
+    Info.Diag(E, diag::note_constexpr_nonliteral)
       << E->getType();
   else
-    Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+    Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
   return false;
 }
 
@@ -1155,7 +1167,7 @@
 template<typename T>
 static bool HandleOverflow(EvalInfo &Info, const Expr *E,
                            const T &SrcValue, QualType DestType) {
-  Info.Diag(E->getExprLoc(), diag::note_constexpr_overflow)
+  Info.Diag(E, diag::note_constexpr_overflow)
     << SrcValue << DestType;
   return false;
 }
@@ -1240,7 +1252,7 @@
       } else {
         // Don't try to handle vectors of anything other than int or float
         // (not sure if it's possible to hit this case).
-        Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+        Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
         return false;
       }
       unsigned BaseEltSize = EltAsInt.getBitWidth();
@@ -1253,7 +1265,7 @@
   }
   // Give up if the input isn't an int, float, or vector.  For example, we
   // reject "(v4i16)(intptr_t)&a".
-  Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+  Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
   return false;
 }
 
@@ -1414,7 +1426,7 @@
     if (Info.CheckingPotentialConstantExpression)
       return false;
     if (!Frame || !Frame->Arguments) {
-      Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+      Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
       return false;
     }
     Result = Frame->Arguments[PVD->getFunctionScopeIndex()];
@@ -1427,7 +1439,7 @@
     // If we're checking a potential constant expression, the variable could be
     // initialized later.
     if (!Info.CheckingPotentialConstantExpression)
-      Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+      Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
     return false;
   }
 
@@ -1441,7 +1453,7 @@
   // Never evaluate the initializer of a weak variable. We can't be sure that
   // this is the definition which will be used.
   if (VD->isWeak()) {
-    Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+    Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
     return false;
   }
 
@@ -1449,13 +1461,13 @@
   // this in the cases where it matters for conformance.
   llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
   if (!VD->evaluateValue(Notes)) {
-    Info.Diag(E->getExprLoc(), diag::note_constexpr_var_init_non_constant,
+    Info.Diag(E, diag::note_constexpr_var_init_non_constant,
               Notes.size() + 1) << VD;
     Info.Note(VD->getLocation(), diag::note_declared_at);
     Info.addNotes(Notes);
     return false;
   } else if (!VD->checkInitIsICE()) {
-    Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_var_init_non_constant,
+    Info.CCEDiag(E, diag::note_constexpr_var_init_non_constant,
                  Notes.size() + 1) << VD;
     Info.Note(VD->getLocation(), diag::note_declared_at);
     Info.addNotes(Notes);
@@ -1507,7 +1519,7 @@
     // A diagnostic will have already been produced.
     return false;
   if (Sub.isOnePastTheEnd()) {
-    Info.Diag(E->getExprLoc(), Info.getLangOpts().CPlusPlus0x ?
+    Info.Diag(E, Info.getLangOpts().CPlusPlus0x ?
                 (unsigned)diag::note_constexpr_read_past_end :
                 (unsigned)diag::note_invalid_subexpr_in_const_expr);
     return false;
@@ -1529,7 +1541,7 @@
       if (CAT->getSize().ule(Index)) {
         // Note, it should not be possible to form a pointer with a valid
         // designator which points more than one past the end of the array.
-        Info.Diag(E->getExprLoc(), Info.getLangOpts().CPlusPlus0x ?
+        Info.Diag(E, Info.getLangOpts().CPlusPlus0x ?
                     (unsigned)diag::note_constexpr_read_past_end :
                     (unsigned)diag::note_invalid_subexpr_in_const_expr);
         return false;
@@ -1551,7 +1563,7 @@
       // Next subobject is a complex number.
       uint64_t Index = Sub.Entries[I].ArrayIndex;
       if (Index > 1) {
-        Info.Diag(E->getExprLoc(), Info.getLangOpts().CPlusPlus0x ?
+        Info.Diag(E, Info.getLangOpts().CPlusPlus0x ?
                     (unsigned)diag::note_constexpr_read_past_end :
                     (unsigned)diag::note_invalid_subexpr_in_const_expr);
         return false;
@@ -1568,7 +1580,7 @@
       return true;
     } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) {
       if (Field->isMutable()) {
-        Info.Diag(E->getExprLoc(), diag::note_constexpr_ltor_mutable, 1)
+        Info.Diag(E, diag::note_constexpr_ltor_mutable, 1)
           << Field;
         Info.Note(Field->getLocation(), diag::note_declared_at);
         return false;
@@ -1580,8 +1592,7 @@
         const FieldDecl *UnionField = O->getUnionField();
         if (!UnionField ||
             UnionField->getCanonicalDecl() != Field->getCanonicalDecl()) {
-          Info.Diag(E->getExprLoc(),
-                    diag::note_constexpr_read_inactive_union_member)
+          Info.Diag(E, diag::note_constexpr_read_inactive_union_member)
             << Field << !UnionField << UnionField;
           return false;
         }
@@ -1593,11 +1604,11 @@
       if (ObjType.isVolatileQualified()) {
         if (Info.getLangOpts().CPlusPlus) {
           // FIXME: Include a description of the path to the volatile subobject.
-          Info.Diag(E->getExprLoc(), diag::note_constexpr_ltor_volatile_obj, 1)
+          Info.Diag(E, diag::note_constexpr_ltor_volatile_obj, 1)
             << 2 << Field;
           Info.Note(Field->getLocation(), diag::note_declared_at);
         } else {
-          Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+          Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
         }
         return false;
       }
@@ -1611,7 +1622,7 @@
 
     if (O->isUninit()) {
       if (!Info.CheckingPotentialConstantExpression)
-        Info.Diag(E->getExprLoc(), diag::note_constexpr_read_uninit);
+        Info.Diag(E, diag::note_constexpr_read_uninit);
       return false;
     }
   }
@@ -1702,11 +1713,10 @@
     return false;
 
   const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
-  SourceLocation Loc = Conv->getExprLoc();
 
   if (!LVal.Base) {
     // FIXME: Indirection through a null pointer deserves a specific diagnostic.
-    Info.Diag(Loc, diag::note_invalid_subexpr_in_const_expr);
+    Info.Diag(Conv, diag::note_invalid_subexpr_in_const_expr);
     return false;
   }
 
@@ -1714,7 +1724,7 @@
   if (LVal.CallIndex) {
     Frame = Info.getCallFrame(LVal.CallIndex);
     if (!Frame) {
-      Info.Diag(Loc, diag::note_constexpr_lifetime_ended, 1) << !Base;
+      Info.Diag(Conv, diag::note_constexpr_lifetime_ended, 1) << !Base;
       NoteLValueLocation(Info, LVal.Base);
       return false;
     }
@@ -1726,9 +1736,9 @@
   // semantics.
   if (Type.isVolatileQualified()) {
     if (Info.getLangOpts().CPlusPlus)
-      Info.Diag(Loc, diag::note_constexpr_ltor_volatile_type) << Type;
+      Info.Diag(Conv, diag::note_constexpr_ltor_volatile_type) << Type;
     else
-      Info.Diag(Loc);
+      Info.Diag(Conv);
     return false;
   }
 
@@ -1742,7 +1752,7 @@
     if (const VarDecl *VDef = VD->getDefinition(Info.Ctx))
       VD = VDef;
     if (!VD || VD->isInvalidDecl()) {
-      Info.Diag(Loc);
+      Info.Diag(Conv);
       return false;
     }
 
@@ -1751,10 +1761,10 @@
     QualType VT = VD->getType();
     if (VT.isVolatileQualified()) {
       if (Info.getLangOpts().CPlusPlus) {
-        Info.Diag(Loc, diag::note_constexpr_ltor_volatile_obj, 1) << 1 << VD;
+        Info.Diag(Conv, diag::note_constexpr_ltor_volatile_obj, 1) << 1 << VD;
         Info.Note(VD->getLocation(), diag::note_declared_at);
       } else {
-        Info.Diag(Loc);
+        Info.Diag(Conv);
       }
       return false;
     }
@@ -1765,10 +1775,10 @@
       } else if (VT->isIntegralOrEnumerationType()) {
         if (!VT.isConstQualified()) {
           if (Info.getLangOpts().CPlusPlus) {
-            Info.Diag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
+            Info.Diag(Conv, diag::note_constexpr_ltor_non_const_int, 1) << VD;
             Info.Note(VD->getLocation(), diag::note_declared_at);
           } else {
-            Info.Diag(Loc);
+            Info.Diag(Conv);
           }
           return false;
         }
@@ -1777,18 +1787,18 @@
         // static const data members of such types (supported as an extension)
         // more useful.
         if (Info.getLangOpts().CPlusPlus0x) {
-          Info.CCEDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
+          Info.CCEDiag(Conv, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
           Info.Note(VD->getLocation(), diag::note_declared_at);
         } else {
-          Info.CCEDiag(Loc);
+          Info.CCEDiag(Conv);
         }
       } else {
         // FIXME: Allow folding of values of any literal type in all languages.
         if (Info.getLangOpts().CPlusPlus0x) {
-          Info.Diag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
+          Info.Diag(Conv, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
           Info.Note(VD->getLocation(), diag::note_declared_at);
         } else {
-          Info.Diag(Loc);
+          Info.Diag(Conv);
         }
         return false;
       }
@@ -1812,7 +1822,7 @@
     if (unsigned CallIndex = RVal.getLValueCallIndex()) {
       Frame = Info.getCallFrame(CallIndex);
       if (!Frame) {
-        Info.Diag(Loc, diag::note_constexpr_lifetime_ended, 1) << !Base;
+        Info.Diag(Conv, diag::note_constexpr_lifetime_ended, 1) << !Base;
         NoteLValueLocation(Info, RVal.getLValueBase());
         return false;
       }
@@ -1824,10 +1834,10 @@
   // Volatile temporary objects cannot be read in constant expressions.
   if (Base->getType().isVolatileQualified()) {
     if (Info.getLangOpts().CPlusPlus) {
-      Info.Diag(Loc, diag::note_constexpr_ltor_volatile_obj, 1) << 0;
+      Info.Diag(Conv, diag::note_constexpr_ltor_volatile_obj, 1) << 0;
       Info.Note(Base->getExprLoc(), diag::note_constexpr_temporary_here);
     } else {
-      Info.Diag(Loc);
+      Info.Diag(Conv);
     }
     return false;
   }
@@ -1850,7 +1860,7 @@
     // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
     RVal = APValue(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0);
   } else {
-    Info.Diag(Conv->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+    Info.Diag(Conv, diag::note_invalid_subexpr_in_const_expr);
     return false;
   }
 
@@ -1976,7 +1986,7 @@
 
   // Check this cast lands within the final derived-to-base subobject path.
   if (D.MostDerivedPathLength + E->path_size() > D.Entries.size()) {
-    Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_invalid_downcast)
+    Info.CCEDiag(E, diag::note_constexpr_invalid_downcast)
       << D.MostDerivedType << TargetQT;
     return false;
   }
@@ -1991,7 +2001,7 @@
   else
     FinalType = getAsBaseClass(D.Entries[NewEntriesSize - 1]);
   if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl()) {
-    Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_invalid_downcast)
+    Info.CCEDiag(E, diag::note_constexpr_invalid_downcast)
       << D.MostDerivedType << TargetQT;
     return false;
   }
@@ -2420,13 +2430,13 @@
   typedef ExprEvaluatorBase ExprEvaluatorBaseTy;
 
   OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) {
-    return Info.CCEDiag(E->getExprLoc(), D);
+    return Info.CCEDiag(E, D);
   }
 
   /// Report an evaluation error. This should only be called when an error is
   /// first discovered. When propagating an error, just return false.
   bool Error(const Expr *E, diag::kind D) {
-    Info.Diag(E->getExprLoc(), D);
+    Info.Diag(E, D);
     return false;
   }
   bool Error(const Expr *E) {
@@ -2957,7 +2967,7 @@
     return Success(E);
   CXXRecordDecl *RD = E->getExprOperand()->getType()->getAsCXXRecordDecl();
   if (RD && RD->isPolymorphic()) {
-    Info.Diag(E->getExprLoc(), diag::note_constexpr_typeid_polymorphic)
+    Info.Diag(E, diag::note_constexpr_typeid_polymorphic)
       << E->getExprOperand()->getType()
       << E->getExprOperand()->getSourceRange();
     return false;
@@ -3405,7 +3415,7 @@
   }
 
   if (isa<CXXRecordDecl>(RD) && cast<CXXRecordDecl>(RD)->getNumVBases()) {
-    Info.Diag(E->getExprLoc(), diag::note_constexpr_virtual_base) << RD;
+    Info.Diag(E, diag::note_constexpr_virtual_base) << RD;
     return false;
   }
 
@@ -4115,7 +4125,7 @@
   if (!Val.isInt()) {
     // FIXME: It would be better to produce the diagnostic for casting
     //        a pointer to an integer.
-    Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+    Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
     return false;
   }
   Result = Val.getInt();
@@ -4338,10 +4348,10 @@
   case Builtin::BIstrlen:
     // A call to strlen is not a constant expression.
     if (Info.getLangOpts().CPlusPlus0x)
-      Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_invalid_function)
+      Info.CCEDiag(E, diag::note_constexpr_invalid_function)
         << /*isConstexpr*/0 << /*isConstructor*/0 << "'strlen'";
     else
-      Info.CCEDiag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+      Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
     // Fall through.
   case Builtin::BI__builtin_strlen:
     // As an extension, we support strlen() and __builtin_strlen() as constant
@@ -5981,17 +5991,17 @@
     Result = Info.CurrentCall->Temporaries[E];
   } else if (E->getType()->isVoidType()) {
     if (Info.getLangOpts().CPlusPlus0x)
-      Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_nonliteral)
+      Info.CCEDiag(E, diag::note_constexpr_nonliteral)
         << E->getType();
     else
-      Info.CCEDiag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+      Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr);
     if (!EvaluateVoid(E, Info))
       return false;
   } else if (Info.getLangOpts().CPlusPlus0x) {
-    Info.Diag(E->getExprLoc(), diag::note_constexpr_nonliteral) << E->getType();
+    Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType();
     return false;
   } else {
-    Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
+    Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
     return false;
   }
 





More information about the cfe-commits mailing list