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

John McCall rjmccall at apple.com
Wed May 4 15:56:50 PDT 2011


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().

John.



More information about the cfe-commits mailing list