Give OpaqueValueExpr a source location, because its source location
authorDouglas Gregor <dgregor@apple.com>
Fri, 28 Jan 2011 02:26:04 +0000 (02:26 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 28 Jan 2011 02:26:04 +0000 (02:26 +0000)
might be queried in places where we absolutely require a valid
location (e.g., for template instantiation). Fixes some major
brokenness in the use of __is_convertible_to.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124465 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/Sema/Sema.h
lib/AST/Expr.cpp
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaObjCProperty.cpp
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
test/SemaCXX/type-traits.cpp

index 941a982fe33af31243d0929a6eac00766bb349f7..9fb74d541092a482af9c6d899d05e91d6610fb09 100644 (file)
@@ -3625,15 +3625,22 @@ public:
 /// context.
 class OpaqueValueExpr : public Expr {
   friend class ASTStmtReader;
+  SourceLocation Loc;
+  
 public:
-  OpaqueValueExpr(QualType T, ExprValueKind VK, ExprObjectKind OK = OK_Ordinary)
+  OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, 
+                  ExprObjectKind OK = OK_Ordinary)
     : Expr(OpaqueValueExprClass, T, VK, OK,
-           T->isDependentType(), T->isDependentType(), false) {
+           T->isDependentType(), T->isDependentType(), false), 
+      Loc(Loc) {
   }
 
   explicit OpaqueValueExpr(EmptyShell Empty)
     : Expr(OpaqueValueExprClass, Empty) { }
 
+  /// \brief Retrieve the location of this expression.
+  SourceLocation getLocation() const { return Loc; }
+  
   virtual SourceRange getSourceRange() const;
   virtual child_iterator child_begin();
   virtual child_iterator child_end();
index a905efe8362dcac1135966f551deb7f9a70f959f..781e3588ee0c74fb23fbfe1354582b4c9d3e6214 100644 (file)
@@ -4551,7 +4551,8 @@ public:
   /// CheckAssignmentConstraints - Perform type checking for assignment,
   /// argument passing, variable initialization, and function return values.
   /// C99 6.5.16.
-  AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs);
+  AssignConvertType CheckAssignmentConstraints(SourceLocation Loc,
+                                               QualType lhs, QualType rhs);
 
   /// Check assignment constraints and prepare for a conversion of the
   /// RHS to the LHS type.
index cfe89a8fb0f985deedc5710ba8da77eccecd4068..9e8f801791dade212a4c6e6a8785c29066e673c3 100644 (file)
@@ -2981,7 +2981,7 @@ Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();}
 Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); }
 
 // OpaqueValueExpr
-SourceRange OpaqueValueExpr::getSourceRange() const { return SourceRange(); }
+SourceRange OpaqueValueExpr::getSourceRange() const { return Loc; }
 Stmt::child_iterator OpaqueValueExpr::child_begin() { return child_iterator(); }
 Stmt::child_iterator OpaqueValueExpr::child_end() { return child_iterator(); }
 
index 474c7cb82f9eb5ab20bc484f8bce39aeafe4806a..09fdf8dca464ad250e7ac00afb5ecd281f797d6d 100644 (file)
@@ -1472,7 +1472,8 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   // If this ever proves to be a problem it should be easy to fix.
   QualType Ty = S.Context.getPointerType(VD->getType());
   QualType ParamTy = FD->getParamDecl(0)->getType();
-  if (S.CheckAssignmentConstraints(ParamTy, Ty) != Sema::Compatible) {
+  if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),
+                                   ParamTy, Ty) != Sema::Compatible) {
     S.Diag(Attr.getParameterLoc(),
            diag::err_attribute_cleanup_func_arg_incompatible_type) <<
       Attr.getParameterName() << ParamTy << Ty;
index 3112ccb55f398333f51b300bd8a37f4a9c955e26..098f5396bb099af6f5ba5162ef2af787faf50f34 100644 (file)
@@ -5507,12 +5507,13 @@ Sema::CheckObjCPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
 }
 
 Sema::AssignConvertType
-Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
+Sema::CheckAssignmentConstraints(SourceLocation Loc,
+                                 QualType lhsType, QualType rhsType) {
   // Fake up an opaque expression.  We don't actually care about what
   // cast operations are required, so if CheckAssignmentConstraints
   // adds casts to this they'll be wasted, but fortunately that doesn't
   // usually happen on valid code.
-  OpaqueValueExpr rhs(rhsType, VK_RValue);
+  OpaqueValueExpr rhs(Loc, rhsType, VK_RValue);
   Expr *rhsPtr = &rhs;
   CastKind K = CK_Invalid;
 
@@ -6952,7 +6953,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS,
     }
   } else {
     // Compound assignment "x += y"
-    ConvTy = CheckAssignmentConstraints(LHSType, RHSType);
+    ConvTy = CheckAssignmentConstraints(Loc, LHSType, RHSType);
   }
 
   if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType,
index cf2e10d531f9cfaf6f4b180b80cb9d35ea5112b7..6ba18a54fd0f8d84ff5dd3029a96a4acdb9b8fe5 100644 (file)
@@ -2531,7 +2531,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
       LhsT = Self.Context.getRValueReferenceType(LhsT);
     
     InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT));
-    OpaqueValueExpr From(LhsT.getNonLValueExprType(Self.Context),
+    OpaqueValueExpr From(KeyLoc, LhsT.getNonLValueExprType(Self.Context),
                          Expr::getValueKindForType(LhsT));
     Expr *FromPtr = &From;
     InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, 
index 09512886187309a758a9d2182d976d500ef2b79d..88ad4d7527c3bd9a3afb860cfa4ec230dc3c6e6a 100644 (file)
@@ -440,9 +440,13 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
           Context.canAssignObjCInterfaces(
                                   PropType->getAs<ObjCObjectPointerType>(),
                                   IvarType->getAs<ObjCObjectPointerType>());
-      else 
-        compat = (CheckAssignmentConstraints(PropType, IvarType)
+      else {
+        SourceLocation Loc = PropertyIvarLoc;
+        if (Loc.isInvalid())
+          Loc = PropertyLoc;
+        compat = (CheckAssignmentConstraints(Loc, PropType, IvarType)
                     == Compatible);
+      }
       if (!compat) {
         Diag(PropertyLoc, diag::error_property_ivar_type)
           << property->getDeclName() << PropType
@@ -663,7 +667,7 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
       GetterMethod->getResultType() != property->getType()) {
     AssignConvertType result = Incompatible;
     if (property->getType()->isObjCObjectPointerType())
-      result = CheckAssignmentConstraints(GetterMethod->getResultType(),
+      result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(),
                                           property->getType());
     if (result != Compatible) {
       Diag(Loc, diag::warn_accessor_property_type_mismatch)
index 79b68e63a8e56d96f6a6c09232f6b29ffa0b5602..1a2284bde8718241610da5f816353bae0c52da50 100644 (file)
@@ -1327,6 +1327,7 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr(
 
 void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   VisitExpr(E);
+  E->Loc = ReadSourceLocation(Record, Idx);
 }
 
 Stmt *ASTReader::ReadStmt(PerFileData &F) {
index 3962439ac5ec298fa4a2d3be2fbb2a2097c8528c..601de6d8f626b315b217f9cd4daf8b0a68e1b2d1 100644 (file)
@@ -1332,6 +1332,7 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr(
 
 void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   VisitExpr(E);
+  Writer.AddSourceLocation(E->getLocation(), Record);
   Code = serialization::EXPR_OPAQUE_VALUE;
 }
 
index 0ecec449637b0abdd943436e44d5cfd8fcb9e347..b7f18aa6bd9b8c30e4453dc02b5a09a20a876b63 100644 (file)
@@ -508,6 +508,11 @@ class PrivateCopy {
   friend void is_convertible_to();
 };
 
+template<typename T>
+struct X0 { 
+  template<typename U> X0(const X0<U>&);
+};
+
 void is_convertible_to() {
   int t01[T(__is_convertible_to(Int, Int))];
   int t02[F(__is_convertible_to(Int, IntAr))];
@@ -531,4 +536,5 @@ void is_convertible_to() {
   int t20[F(__is_convertible_to(const IntAr&, IntAr&))];
   int t21[F(__is_convertible_to(Function, Function))];
   int t22[F(__is_convertible_to(PrivateCopy, PrivateCopy))];
+  int t23[T(__is_convertible_to(X0<int>, X0<float>))];
 }