Add support for C++ default arguments, and rework Parse-Sema
interaction for function parameters, fixing PR2046.
Patch by Doug Gregor!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49369 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f4ef283..6a6cd25 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -15,6 +15,7 @@
#include "SemaUtil.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/LiteralSupport.h"
@@ -594,15 +595,25 @@
Expr *Fn = static_cast<Expr *>(fn);
Expr **Args = reinterpret_cast<Expr**>(args);
assert(Fn && "no function call expression");
-
+ FunctionDecl *FDecl = NULL;
+ unsigned NumArgsPassed = NumArgs;
+
+ // Promote the function operand.
+ UsualUnaryConversions(Fn);
+
+ // If we're directly calling a function, get the declaration for
+ // that function.
+ if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
+ if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()))
+ FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl());
+
// Make the call expr early, before semantic checks. This guarantees cleanup
// of arguments and function on error.
- llvm::OwningPtr<CallExpr> TheCall(new CallExpr(Fn, Args, NumArgs,
+ if (getLangOptions().CPlusPlus && FDecl && NumArgs < FDecl->getNumParams())
+ NumArgsPassed = FDecl->getNumParams();
+ llvm::OwningPtr<CallExpr> TheCall(new CallExpr(Fn, Args, NumArgsPassed,
Context.BoolTy, RParenLoc));
- // Promote the function operand.
- TheCall->setCallee(UsualUnaryConversions(Fn));
-
// C99 6.5.2.2p1 - "The expression that denotes the called function shall have
// type pointer to function".
const PointerType *PT = Fn->getType()->getAsPointerType();
@@ -623,11 +634,19 @@
unsigned NumArgsInProto = Proto->getNumArgs();
unsigned NumArgsToCheck = NumArgs;
- // If too few arguments are available, don't make the call.
- if (NumArgs < NumArgsInProto)
- return Diag(RParenLoc, diag::err_typecheck_call_too_few_args,
- Fn->getSourceRange());
-
+ // If too few arguments are available (and we don't have default
+ // arguments for the remaining parameters), don't make the call.
+ if (NumArgs < NumArgsInProto) {
+ if (getLangOptions().CPlusPlus &&
+ FDecl &&
+ FDecl->getParamDecl(NumArgs)->getDefaultArg()) {
+ // Use default arguments for missing arguments
+ NumArgsToCheck = NumArgsInProto;
+ } else
+ return Diag(RParenLoc, diag::err_typecheck_call_too_few_args,
+ Fn->getSourceRange());
+ }
+
// If too many are passed and not variadic, error on the extras and drop
// them.
if (NumArgs > NumArgsInProto) {
@@ -644,8 +663,13 @@
// Continue to check argument types (even if we have too few/many args).
for (unsigned i = 0; i != NumArgsToCheck; i++) {
- Expr *Arg = Args[i];
QualType ProtoArgType = Proto->getArgType(i);
+
+ Expr *Arg;
+ if (i < NumArgs)
+ Arg = Args[i];
+ else
+ Arg = new CXXDefaultArgExpr(FDecl->getParamDecl(i));
QualType ArgType = Arg->getType();
// Compute implicit casts from the operand to the formal argument type.
@@ -679,11 +703,8 @@
}
// Do special checking on direct calls to functions.
- if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(Fn))
- if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr()))
- if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()))
- if (CheckFunctionCall(FDecl, TheCall.get()))
- return true;
+ if (FDecl && CheckFunctionCall(FDecl, TheCall.get()))
+ return true;
return TheCall.take();
}