[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