[cfe-commits] r72076 - in /cfe/trunk: lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplateInstantiateExpr.cpp test/SemaTemplate/instantiate-subscript.cpp

Douglas Gregor dgregor at apple.com
Mon May 18 17:01:20 PDT 2009


Author: dgregor
Date: Mon May 18 19:01:19 2009
New Revision: 72076

URL: http://llvm.org/viewvc/llvm-project?rev=72076&view=rev
Log:
Template instantiation for array subscript expressions. This was far
easier than expected because of the limitation that subscript
operators must be member functions.

Added:
    cfe/trunk/test/SemaTemplate/instantiate-subscript.cpp
Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon May 18 19:01:19 2009
@@ -1665,6 +1665,14 @@
        *RHSExp = static_cast<Expr*>(Idx.get());
 
   if (getLangOptions().CPlusPlus &&
+      (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) {
+    Base.release();
+    Idx.release();
+    return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
+                                                  Context.DependentTy, RLoc));
+  }
+
+  if (getLangOptions().CPlusPlus && 
       (LHSExp->getType()->isRecordType() ||
        LHSExp->getType()->isEnumeralType() ||
        RHSExp->getType()->isRecordType() ||

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon May 18 19:01:19 2009
@@ -2402,7 +2402,8 @@
     T2 = Args[1]->getType();
 
   DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
-  LookupOverloadedOperatorName(Op, S, T1, T2, Functions);
+  if (S)
+    LookupOverloadedOperatorName(Op, S, T1, T2, Functions);
   ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
   AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet);
   AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Mon May 18 19:01:19 2009
@@ -45,6 +45,7 @@
     OwningExprResult VisitDeclRefExpr(DeclRefExpr *E);
     OwningExprResult VisitParenExpr(ParenExpr *E);
     OwningExprResult VisitUnaryOperator(UnaryOperator *E);
+    OwningExprResult VisitArraySubscriptExpr(ArraySubscriptExpr *E);
     OwningExprResult VisitBinaryOperator(BinaryOperator *E);
     OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
     OwningExprResult VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E);
@@ -173,6 +174,36 @@
 }
 
 Sema::OwningExprResult 
+TemplateExprInstantiator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
+  Sema::OwningExprResult LHS = Visit(E->getLHS());
+  if (LHS.isInvalid())
+    return SemaRef.ExprError();
+
+  Sema::OwningExprResult RHS = Visit(E->getRHS());
+  if (RHS.isInvalid())
+    return SemaRef.ExprError();
+
+  // Since the overloaded array-subscript operator (operator[]) can
+  // only be a member function, we can make several simplifying
+  // assumptions here:
+  //   1) Normal name lookup (from the current scope) will not ever
+  //   find any declarations of operator[] that won't also be found be
+  //   member operator lookup, so it is safe to pass a NULL Scope
+  //   during the instantiation to avoid the lookup entirely.
+  //
+  //   2) Neither normal name lookup nor argument-dependent lookup at
+  //   template definition time will find any operators that won't be
+  //   found at template instantiation time, so we do not need to
+  //   cache the results of name lookup as we do for the binary
+  //   operators.
+  SourceLocation LLocFake = ((Expr*)LHS.get())->getSourceRange().getBegin();
+  return SemaRef.ActOnArraySubscriptExpr(/*Scope=*/0, move(LHS),
+                                         /*FIXME:*/LLocFake,
+                                         move(RHS),
+                                         E->getRBracketLoc());
+}
+
+Sema::OwningExprResult 
 TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) {
   Sema::OwningExprResult LHS = Visit(E->getLHS());
   if (LHS.isInvalid())

Added: cfe/trunk/test/SemaTemplate/instantiate-subscript.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-subscript.cpp?rev=72076&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-subscript.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-subscript.cpp Mon May 18 19:01:19 2009
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+
+struct Sub0 {
+  int &operator[](int);
+};
+
+struct Sub1 {
+  long &operator[](long);
+};
+
+struct ConvertibleToInt {
+  operator int();
+};
+
+template<typename T, typename U, typename Result>
+struct Subscript0 {
+  void test(T t, U u) {
+    Result &result = t[u]; // expected-error{{subscripted value is not}}
+  }
+};
+
+template struct Subscript0<int*, int, int&>;
+template struct Subscript0<Sub0, int, int&>;
+template struct Subscript0<Sub1, ConvertibleToInt, long&>;
+template struct Subscript0<Sub1, Sub0, long&>; // expected-note{{instantiation}}





More information about the cfe-commits mailing list