[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