diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-07-13 08:18:22 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-07-13 08:18:22 +0000 |
commit | 603d81bf8d055732b3ba24899dd9c443e1ef243b (patch) | |
tree | ddea48df7318af2c406d98e6bbeee74b066139ae /clang/lib | |
parent | d8f446f1b2dbe66cfa30335b60d6217fef684811 (diff) | |
download | bcm5719-llvm-603d81bf8d055732b3ba24899dd9c443e1ef243b.tar.gz bcm5719-llvm-603d81bf8d055732b3ba24899dd9c443e1ef243b.zip |
When forming a function call or message send expression, be sure to
strip cv-qualifiers from the expression's type when the language calls
for it: in C, that's all the time, while C++ only does it for
non-class types.
Centralized the computation of the call expression type in
QualType::getCallResultType() and some helper functions in other nodes
(FunctionDecl, ObjCMethodDecl, FunctionType), and updated all relevant
callers of getResultType() to getCallResultType().
Fixes PR7598 and PR7463, along with a bunch of getResultType() call
sites that weren't stripping references off the result type (nothing
stripped cv-qualifiers properly before this change).
llvm-svn: 108234
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 5 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Rewrite/RewriteObjC.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 2 |
12 files changed, 71 insertions, 27 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index cc6ad5ab466..bd97b886fe1 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -576,7 +576,10 @@ QualType CallExpr::getCallReturnType() const { CalleeType = FnTypePtr->getPointeeType(); else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>()) CalleeType = BPT->getPointeeType(); - + else if (const MemberPointerType *MPT + = CalleeType->getAs<MemberPointerType>()) + CalleeType = MPT->getPointeeType(); + const FunctionType *FnType = CalleeType->getAs<FunctionType>(); return FnType->getResultType(); } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 5a7aa89d6df..ab64eafbee2 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -992,6 +992,22 @@ const char *BuiltinType::getName(const LangOptions &LO) const { void FunctionType::ANCHOR() {} // Key function for FunctionType. +QualType QualType::getCallResultType(ASTContext &Context) const { + if (const ReferenceType *RefType = getTypePtr()->getAs<ReferenceType>()) + return RefType->getPointeeType(); + + // C++0x [basic.lval]: + // Class prvalues can have cv-qualified types; non-class prvalues always + // have cv-unqualified types. + // + // See also C99 6.3.2.1p2. + if (!Context.getLangOptions().CPlusPlus || + !getTypePtr()->isDependentType() && !getTypePtr()->isRecordType()) + return getUnqualifiedType(); + + return *this; +} + llvm::StringRef FunctionType::getNameForCallConv(CallingConv CC) { switch (CC) { case CC_Default: llvm_unreachable("no name for default cc"); diff --git a/clang/lib/Rewrite/RewriteObjC.cpp b/clang/lib/Rewrite/RewriteObjC.cpp index 204ec264156..489fec9be0e 100644 --- a/clang/lib/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Rewrite/RewriteObjC.cpp @@ -2113,8 +2113,8 @@ CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl( const FunctionType *FT = msgSendType->getAs<FunctionType>(); CallExpr *Exp = - new (Context) CallExpr(*Context, ICE, args, nargs, FT->getResultType(), - EndLoc); + new (Context) CallExpr(*Context, ICE, args, nargs, + FT->getCallResultType(*Context), EndLoc); return Exp; } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 217ada01c6b..7a39f058c5e 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -561,7 +561,7 @@ Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) { TheCall->setCallee(PromotedCall); // Change the result type of the call to match the result type of the decl. - TheCall->setType(NewBuiltinDecl->getResultType()); + TheCall->setType(NewBuiltinDecl->getCallResultType()); // If the value type was converted to an integer when processing the // arguments (e.g. void* -> int), we need to convert the result back. diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 6a706dfefe5..82861101e83 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -567,11 +567,11 @@ static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) { QualType T; if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) - T = Function->getResultType(); + T = Function->getCallResultType(); else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) - T = Method->getResultType(); + T = Method->getSendResultType(); else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) - T = FunTmpl->getTemplatedDecl()->getResultType(); + T = FunTmpl->getTemplatedDecl()->getCallResultType(); else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 9f9858001e6..ce3bf11caa0 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3004,7 +3004,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, QualType PType; if (Getter) - PType = Getter->getResultType(); + PType = Getter->getSendResultType(); else // Get the expression type from Setter's incoming parameter. PType = (*(Setter->param_end() -1))->getType(); @@ -3180,7 +3180,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, return ExprError(); return Owned(ObjCMessageExpr::Create(Context, - OMD->getResultType().getNonReferenceType(), + OMD->getSendResultType(), OpLoc, BaseExpr, Sel, OMD, NULL, 0, MemberLoc)); } @@ -3575,7 +3575,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, BO->getOpcode() == BinaryOperator::PtrMemI) { if (const FunctionProtoType *FPT = BO->getType()->getAs<FunctionProtoType>()) { - QualType ResultTy = FPT->getResultType().getNonReferenceType(); + QualType ResultTy = FPT->getCallResultType(Context); ExprOwningPtr<CXXMemberCallExpr> TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args, @@ -3665,7 +3665,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, return ExprError(); // We know the result type of the call, set it. - TheCall->setType(FuncT->getResultType().getNonReferenceType()); + TheCall->setType(FuncT->getCallResultType(Context)); if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) { if (ConvertArgumentsForCall(&*TheCall, Fn, FDecl, Proto, Args, NumArgs, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 180b5911bfc..5c693ab358e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3032,7 +3032,7 @@ CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, MemberExpr *ME = new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method, SourceLocation(), Method->getType()); - QualType ResultType = Method->getResultType().getNonReferenceType(); + QualType ResultType = Method->getCallResultType(); MarkDeclarationReferenced(Exp->getLocStart(), Method); CXXMemberCallExpr *CE = new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 520ea2af91b..9f43471e0ad 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -207,7 +207,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, return false; } - ReturnType = Method->getResultType().getNonReferenceType(); + ReturnType = Method->getSendResultType(); unsigned NumNamedArgs = Sel.getNumArgs(); // Method might have more arguments than selector indicates. This is due @@ -346,7 +346,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) - ResTy = Getter->getResultType(); + ResTy = Getter->getSendResultType(); return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, MemberLoc, BaseExpr)); } @@ -402,7 +402,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (Getter) { QualType PType; - PType = Getter->getResultType(); + PType = Getter->getSendResultType(); return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType, Setter, MemberLoc, BaseExpr)); } @@ -510,7 +510,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, QualType PType; if (Getter) - PType = Getter->getResultType(); + PType = Getter->getSendResultType(); else { for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(), E = Setter->param_end(); PI != E; ++PI) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 5571c1b3824..7536289afc1 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2942,7 +2942,7 @@ static void TryUserDefinedConversion(Sema &S, } // Add the user-defined conversion step that calls the conversion function. - QualType ConvType = Function->getResultType().getNonReferenceType(); + QualType ConvType = Function->getCallResultType(); if (ConvType->getAs<RecordType>()) { // If we're converting to a class type, there may be an copy if // the resulting temporary object (possible to create an object of diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 5b511d7d03c..ee4c479f728 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6668,7 +6668,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); // Determine the result type - QualType ResultTy = FnDecl->getResultType().getNonReferenceType(); + QualType ResultTy = FnDecl->getCallResultType(); // Build the actual expression node. Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), @@ -6875,8 +6875,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Determine the result type QualType ResultTy - = FnDecl->getType()->getAs<FunctionType>()->getResultType(); - ResultTy = ResultTy.getNonReferenceType(); + = FnDecl->getType()->getAs<FunctionType>() + ->getCallResultType(Context); // Build the actual expression node. Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), @@ -7032,8 +7032,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Determine the result type QualType ResultTy - = FnDecl->getType()->getAs<FunctionType>()->getResultType(); - ResultTy = ResultTy.getNonReferenceType(); + = FnDecl->getType()->getAs<FunctionType>() + ->getCallResultType(Context); // Build the actual expression node. Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), @@ -7221,7 +7221,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, ExprOwningPtr<CXXMemberCallExpr> TheCall(this, new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, - Method->getResultType().getNonReferenceType(), + Method->getCallResultType(), RParenLoc)); // Check for a valid return type. @@ -7436,7 +7436,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Once we've built TheCall, all of the expressions are properly // owned. - QualType ResultTy = Method->getResultType().getNonReferenceType(); + QualType ResultTy = Method->getCallResultType(); ExprOwningPtr<CXXOperatorCallExpr> TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn, MethodArgs, NumArgs + 1, @@ -7592,7 +7592,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { SourceLocation()); UsualUnaryConversions(FnExpr); - QualType ResultTy = Method->getResultType().getNonReferenceType(); + QualType ResultTy = Method->getCallResultType(); ExprOwningPtr<CXXOperatorCallExpr> TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr, &Base, 1, ResultTy, OpLoc)); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 48bf7cbac4e..dc3cea1a3c5 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -818,7 +818,7 @@ QualType Sema::BuildFunctionType(QualType T, << T->isFunctionType() << T; return QualType(); } - + bool Invalid = false; for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) { QualType ParamType = adjustParameterType(ParamTypes[Idx]); @@ -1129,6 +1129,31 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, D.setInvalidType(true); } + // cv-qualifiers on return types are pointless except when the type is a + // class type in C++. + if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() && + (!getLangOptions().CPlusPlus || + (!T->isDependentType() && !T->isRecordType()))) { + unsigned Quals = D.getDeclSpec().getTypeQualifiers(); + SourceLocation Loc; + if (Quals & Qualifiers::Const) + Loc = D.getDeclSpec().getConstSpecLoc(); + else if (Quals & Qualifiers::Volatile) + Loc = D.getDeclSpec().getVolatileSpecLoc(); + else { + assert((Quals & Qualifiers::Restrict) && "Unknown type qualifier"); + Loc = D.getDeclSpec().getRestrictSpecLoc(); + } + + SemaDiagnosticBuilder DB = Diag(Loc, diag::warn_qual_return_type); + if (Quals & Qualifiers::Const) + DB << FixItHint::CreateRemoval(D.getDeclSpec().getConstSpecLoc()); + if (Quals & Qualifiers::Volatile) + DB << FixItHint::CreateRemoval(D.getDeclSpec().getVolatileSpecLoc()); + if (Quals & Qualifiers::Restrict) + DB << FixItHint::CreateRemoval(D.getDeclSpec().getRestrictSpecLoc()); + } + if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) { // C++ [dcl.fct]p6: // Types shall not be defined in return or parameter types. diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index db5e2d10f44..f3ad6c8b4b7 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1952,7 +1952,7 @@ public: Expr **Subs = (Expr **)SubExprs.release(); CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee, Subs, NumSubExprs, - Builtin->getResultType(), + Builtin->getCallResultType(), RParenLoc); OwningExprResult OwnedCall(SemaRef.Owned(TheCall)); |