[cfe-commits] r86087 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp lib/Sema/TreeTransform.h test/SemaTemplate/instantiate-expr-1.cpp

Douglas Gregor dgregor at apple.com
Wed Nov 4 16:51:45 PST 2009


Author: dgregor
Date: Wed Nov  4 18:51:44 2009
New Revision: 86087

URL: http://llvm.org/viewvc/llvm-project?rev=86087&view=rev
Log:
When instantiating a UnaryOperator, allow the resulting expression to
still be dependent or invoke an overloaded operator. Previously, we
only supported builtin operators.

BinaryOperator/CompoundAssignOperator didn't have this issue because
we always built a CXXOperatorCallExpr node, even when name lookup
didn't find any functions to save until instantiation time. Now, that
code builds a BinaryOperator or CompoundAssignOperator rather than a
CXXOperatorCallExpr, to save some space.


Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=86087&r1=86086&r2=86087&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov  4 18:51:44 2009
@@ -1667,6 +1667,8 @@
   OwningExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc,
                                         unsigned OpcIn,
                                         ExprArg InputArg);
+  OwningExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+                                UnaryOperator::Opcode Opc, ExprArg input);
   virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
                                         tok::TokenKind Op, ExprArg Input);
 
@@ -1792,6 +1794,9 @@
   virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
                                       tok::TokenKind Kind,
                                       ExprArg LHS, ExprArg RHS);
+  OwningExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
+                              BinaryOperator::Opcode Opc,
+                              Expr *lhs, Expr *rhs);
   OwningExprResult CreateBuiltinBinOp(SourceLocation TokLoc,
                                       unsigned Opc, Expr *lhs, Expr *rhs);
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=86087&r1=86086&r2=86087&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Nov  4 18:51:44 2009
@@ -5509,6 +5509,12 @@
   // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
   DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs);
 
+  return BuildBinOp(S, TokLoc, Opc, lhs, rhs);
+}
+
+Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
+                                          BinaryOperator::Opcode Opc,
+                                          Expr *lhs, Expr *rhs) {
   if (getLangOptions().CPlusPlus &&
       (lhs->getType()->isOverloadableType() ||
        rhs->getType()->isOverloadableType())) {
@@ -5519,21 +5525,22 @@
     FunctionSet Functions;
     OverloadedOperatorKind OverOp = BinaryOperator::getOverloadedOperator(Opc);
     if (OverOp != OO_None) {
-      LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
-                                   Functions);
+      if (S)
+        LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
+                                     Functions);
       Expr *Args[2] = { lhs, rhs };
       DeclarationName OpName
         = Context.DeclarationNames.getCXXOperatorName(OverOp);
       ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions);
     }
-
+    
     // Build the (potentially-overloaded, potentially-dependent)
     // binary operation.
-    return CreateOverloadedBinOp(TokLoc, Opc, Functions, lhs, rhs);
+    return CreateOverloadedBinOp(OpLoc, Opc, Functions, lhs, rhs);
   }
-
+  
   // Build a built-in binary operation.
-  return CreateBuiltinBinOp(TokLoc, Opc, lhs, rhs);
+  return CreateBuiltinBinOp(OpLoc, Opc, lhs, rhs);
 }
 
 Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
@@ -5624,12 +5631,10 @@
   return Owned(new (Context) UnaryOperator(Input, Opc, resultType, OpLoc));
 }
 
-// Unary Operators.  'Tok' is the token for the operator.
-Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
-                                            tok::TokenKind Op, ExprArg input) {
+Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+                                            UnaryOperator::Opcode Opc,
+                                            ExprArg input) {
   Expr *Input = (Expr*)input.get();
-  UnaryOperator::Opcode Opc = ConvertTokenKindToUnaryOpcode(Op);
-
   if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType()) {
     // Find all of the overloaded operators visible from this
     // point. We perform both an operator-name lookup from the local
@@ -5638,19 +5643,26 @@
     FunctionSet Functions;
     OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
     if (OverOp != OO_None) {
-      LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
-                                   Functions);
+      if (S)
+        LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
+                                     Functions);
       DeclarationName OpName
         = Context.DeclarationNames.getCXXOperatorName(OverOp);
       ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions);
     }
-
+    
     return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
   }
-
+  
   return CreateBuiltinUnaryOp(OpLoc, Opc, move(input));
 }
 
+// Unary Operators.  'Tok' is the token for the operator.
+Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+                                            tok::TokenKind Op, ExprArg input) {
+  return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), move(input));
+}
+
 /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
 Sema::OwningExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
                                             SourceLocation LabLoc,

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=86087&r1=86086&r2=86087&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Nov  4 18:51:44 2009
@@ -4787,11 +4787,20 @@
   // If either side is type-dependent, create an appropriate dependent
   // expression.
   if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
-    // .* cannot be overloaded.
-    if (Opc == BinaryOperator::PtrMemD)
-      return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
-                                                Context.DependentTy, OpLoc));
-
+    if (Functions.empty()) {
+      // If there are no functions to store, just build a dependent 
+      // BinaryOperator or CompoundAssignment.
+      if (Opc <= BinaryOperator::Assign || Opc > BinaryOperator::OrAssign)
+        return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
+                                                  Context.DependentTy, OpLoc));
+      
+      return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
+                                                        Context.DependentTy,
+                                                        Context.DependentTy,
+                                                        Context.DependentTy,
+                                                        OpLoc));
+    }
+    
     OverloadedFunctionDecl *Overloads
       = OverloadedFunctionDecl::Create(Context, CurContext, OpName);
     for (FunctionSet::iterator Func = Functions.begin(),

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=86087&r1=86086&r2=86087&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Nov  4 18:51:44 2009
@@ -877,7 +877,7 @@
   OwningExprResult RebuildUnaryOperator(SourceLocation OpLoc,
                                         UnaryOperator::Opcode Opc,
                                         ExprArg SubExpr) {
-    return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, move(SubExpr));
+    return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, move(SubExpr));
   }
 
   /// \brief Build a new sizeof or alignof expression with a type argument.
@@ -986,15 +986,8 @@
   OwningExprResult RebuildBinaryOperator(SourceLocation OpLoc,
                                          BinaryOperator::Opcode Opc,
                                          ExprArg LHS, ExprArg RHS) {
-    OwningExprResult Result
-      = getSema().CreateBuiltinBinOp(OpLoc, Opc, (Expr *)LHS.get(),
-                                     (Expr *)RHS.get());
-    if (Result.isInvalid())
-      return SemaRef.ExprError();
-
-    LHS.release();
-    RHS.release();
-    return move(Result);
+    return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc, 
+                                LHS.takeAs<Expr>(), RHS.takeAs<Expr>());
   }
 
   /// \brief Build a new conditional operator expression.

Modified: cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp?rev=86087&r1=86086&r2=86087&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-expr-1.cpp Wed Nov  4 18:51:44 2009
@@ -1,5 +1,4 @@
 // RUN: clang-cc -fsyntax-only -verify %s
-
 template<int I, int J>
 struct Bitfields {
   int simple : I; // expected-error{{bit-field 'simple' has zero width}}
@@ -69,3 +68,29 @@
   (void)sizeof(BitfieldNeg2<int, -5>); // okay
   (void)sizeof(BitfieldNeg2<int, 5>); // expected-note{{in instantiation of template class 'struct BitfieldNeg2<int, 5>' requested here}}
 }
+
+template<typename T>
+void increment(T &x) {
+  (void)++x;
+}
+
+struct Incrementable {
+  Incrementable &operator++();
+};
+
+void test_increment(Incrementable inc) {
+  increment(inc);
+}
+
+template<typename T>
+void add(const T &x) {
+  (void)(x + x);
+}
+
+struct Addable {
+  Addable operator+(const Addable&) const;
+};
+
+void test_add(Addable &a) {
+  add(a);
+}





More information about the cfe-commits mailing list