[cfe-commits] r130878 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp test/SemaCXX/member-expr.cpp

Matt Beaumont-Gay matthewbg at google.com
Wed May 4 17:20:52 PDT 2011


On Wed, May 4, 2011 at 15:56, John McCall <rjmccall at apple.com> wrote:
>
> On May 4, 2011, at 3:10 PM, Matt Beaumont-Gay wrote:
>
>> Author: matthewbg
>> Date: Wed May  4 17:10:40 2011
>> New Revision: 130878
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=130878&view=rev
>> Log:
>> Implement Sema::isExprCallable.
>>
>> We can use this to produce nice diagnostics (and try to fixit-and-recover) in
>> various cases where we might see "MyFunction" instead of "MyFunction()". The
>> changes in SemaExpr are an example of how to use isExprCallable.
>>
>> Modified:
>>    cfe/trunk/include/clang/Sema/Sema.h
>>    cfe/trunk/lib/Sema/Sema.cpp
>>    cfe/trunk/lib/Sema/SemaExpr.cpp
>>    cfe/trunk/test/SemaCXX/member-expr.cpp
>>
>> Modified: cfe/trunk/include/clang/Sema/Sema.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=130878&r1=130877&r2=130878&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Sema/Sema.h (original)
>> +++ cfe/trunk/include/clang/Sema/Sema.h Wed May  4 17:10:40 2011
>> @@ -2074,7 +2074,14 @@
>>   void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
>>   void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
>>   void MarkDeclarationsReferencedInExpr(Expr *E);
>> -
>> +
>> +  /// \brief Figure out if an expression could be turned into a call.
>> +  bool isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
>> +                      UnresolvedSetImpl &NonTemplateOverloads);
>> +  /// \brief Give notes for a set of overloads.
>> +  void NoteOverloads(const UnresolvedSetImpl &Overloads,
>> +                     const SourceLocation FinalNoteLoc);
>> +
>>   /// \brief Conditionally issue a diagnostic based on the current
>>   /// evaluation context.
>>   ///
>>
>> Modified: cfe/trunk/lib/Sema/Sema.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=130878&r1=130877&r2=130878&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/Sema.cpp (original)
>> +++ cfe/trunk/lib/Sema/Sema.cpp Wed May  4 17:10:40 2011
>> @@ -31,6 +31,7 @@
>> #include "clang/AST/DeclCXX.h"
>> #include "clang/AST/DeclObjC.h"
>> #include "clang/AST/Expr.h"
>> +#include "clang/AST/ExprCXX.h"
>> #include "clang/AST/StmtCXX.h"
>> #include "clang/Lex/Preprocessor.h"
>> #include "clang/Basic/PartialDiagnostic.h"
>> @@ -766,3 +767,102 @@
>>
>>   OS << '\n';
>> }
>> +
>> +/// \brief Figure out if an expression could be turned into a call.
>> +///
>> +/// Use this when trying to recover from an error where the programmer may have
>> +/// written just the name of a function instead of actually calling it.
>> +///
>> +/// \param E - The expression to examine.
>> +/// \param ZeroArgCallReturnTy - If the expression can be turned into a call
>> +///  with no arguments, this parameter is set to the type returned by such a
>> +///  call; otherwise, it is set to an empty QualType.
>> +/// \param NonTemplateOverloads - If the expression is an overloaded function
>> +///  name, this parameter is populated with the decls of the various overloads.
>> +bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
>> +                          UnresolvedSetImpl &NonTemplateOverloads) {
>> +  ZeroArgCallReturnTy = QualType();
>> +  NonTemplateOverloads.clear();
>> +  if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(&E)) {
>> +    for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
>> +         DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
>> +      // Our overload set may include TemplateDecls, which we'll ignore for our
>> +      // present purpose.
>> +      if (const FunctionDecl *OverloadDecl = dyn_cast<FunctionDecl>(*it)) {
>> +        NonTemplateOverloads.addDecl(*it);
>> +        if (OverloadDecl->getMinRequiredArguments() == 0)
>> +          ZeroArgCallReturnTy = OverloadDecl->getResultType();
>> +      }
>> +    }
>> +    return true;
>> +  }
>> +
>> +  if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(&E)) {
>> +    if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
>> +      if (Fun->getMinRequiredArguments() == 0)
>> +        ZeroArgCallReturnTy = Fun->getResultType();
>> +      return true;
>> +    }
>> +  }
>> +
>> +  // We don't have an expression that's convenient to get a FunctionDecl from,
>> +  // but we can at least check if the type is "function of 0 arguments".
>> +  QualType ExprTy = E.getType();
>> +  const FunctionType *FunTy = NULL;
>> +  if (const PointerType *Ptr = ExprTy->getAs<PointerType>())
>> +    FunTy = Ptr->getPointeeType()->getAs<FunctionType>();
>> +  else if (const ReferenceType *Ref = ExprTy->getAs<ReferenceType>())
>> +    FunTy = Ref->getPointeeType()->getAs<FunctionType>();
>
> Please look through BlockPointerTypes here, too.
>
>> +  if (!FunTy)
>> +    FunTy = ExprTy->getAs<FunctionType>();
>> +  if (!FunTy && ExprTy == Context.BoundMemberTy) {
>> +    // Look for the bound-member type.  If it's still overloaded, give up,
>> +    // although we probably should have fallen into the OverloadExpr case above
>> +    // if we actually have an overloaded bound member.
>> +    QualType BoundMemberTy = Expr::findBoundMemberType(&E);
>> +    if (!BoundMemberTy.isNull())
>> +      FunTy = BoundMemberTy->castAs<FunctionType>();
>
> For what it's worth, that's not true;  if all the functions in an overload set for
> are non-static member functions, the expression will have BoundMember
> type.  This is a useful case to get right, too, because a lot of common
> member functions are overloaded, like the STL's begin() and end().

Take a guess who added the original version of this snippet to SemaExpr :)
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?r1=130239&r2=130238&pathrev=130239

I'm not clear on what part of this you're saying is untrue. FWIW, for
simple cases involving member functions, we do the right thing:

  struct S { int x; };
  struct T {
    S fun() { return S(); }
    S fun(int i) { return S(); }
  };
  int g() {
    T t;
    return t.fun.x;
  }

member-expr.cpp:156:12: error: base of member reference is an
overloaded function; perhaps you meant to call it with no arguments?
    return t.fun.x;
           ^~~~~
                ()




More information about the cfe-commits mailing list