diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 35 | 
3 files changed, 46 insertions, 3 deletions
| diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index be300539ebd..aa0b41bc7a6 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4846,6 +4846,7 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {        if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {          MD->addOverriddenMethod(OldMD->getCanonicalDecl());          if (!CheckOverridingFunctionReturnType(MD, OldMD) && +            !CheckOverridingFunctionAttributes(MD, OldMD) &&              !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&              !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {            hasDeletedOverridenMethods |= OldMD->isDeleted(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e36ba2a4578..502b358315a 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3557,10 +3557,11 @@ static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {  static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {    if (hasDeclarator(D)) return; +  const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);    // Diagnostic is emitted elsewhere: here we store the (valid) Attr    // in the Decl node for syntactic reasoning, e.g., pretty-printing.    CallingConv CC; -  if (S.CheckCallingConvAttr(Attr, CC)) +  if (S.CheckCallingConvAttr(Attr, CC, FD))      return;    if (!isa<ObjCMethodDecl>(D)) { @@ -3615,7 +3616,8 @@ static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){    D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context));  } -bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { +bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,  +                                const FunctionDecl *FD) {    if (attr.isInvalid())      return true; @@ -3665,7 +3667,12 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) {    TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC);    if (A == TargetInfo::CCCR_Warning) {      Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName(); -    CC = TI.getDefaultCallingConv(); + +    TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown; +    if (FD) +      MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member :  +                                    TargetInfo::CCMT_NonMember; +    CC = TI.getDefaultCallingConv(MT);    }    return false; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 6f1b489a2d2..2fae8c9f91b 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -26,6 +26,7 @@  #include "clang/AST/TypeLoc.h"  #include "clang/AST/TypeOrdering.h"  #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/TargetInfo.h"  #include "clang/Lex/Preprocessor.h"  #include "clang/Sema/CXXFieldCollector.h"  #include "clang/Sema/DeclSpec.h" @@ -10950,6 +10951,40 @@ void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {    }  } +bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
 +                                             const CXXMethodDecl *Old) { +  const FunctionType *NewFT = New->getType()->getAs<FunctionType>(); +  const FunctionType *OldFT = Old->getType()->getAs<FunctionType>(); + +  CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv(); + +  // If the calling conventions match, everything is fine +  if (NewCC == OldCC) +    return false; + +  // If either of the calling conventions are set to "default", we need to pick +  // something more sensible based on the target. This supports code where the +  // one method explicitly sets thiscall, and another has no explicit calling +  // convention. +  CallingConv Default =  +    Context.getTargetInfo().getDefaultCallingConv(TargetInfo::CCMT_Member); +  if (NewCC == CC_Default) +    NewCC = Default; +  if (OldCC == CC_Default) +    OldCC = Default; + +  // If the calling conventions still don't match, then report the error +  if (NewCC != OldCC) { +    Diag(New->getLocation(),
 +         diag::err_conflicting_overriding_cc_attributes)
 +      << New->getDeclName() << New->getType() << Old->getType();
 +    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
 +    return true;
 +  } + +  return false; +} +  bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,                                               const CXXMethodDecl *Old) {    QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType(); | 

