Commit 3e09fa6f authored by Bill Wendling's avatar Bill Wendling
Browse files

Merging r196050:

------------------------------------------------------------------------
r196050 | rafael | 2013-12-01 08:54:29 -0800 (Sun, 01 Dec 2013) | 5 lines

Handle CC and NoReturn when instantiating members of class templates.

Before we were considering them only when instantiating templates.

This fixes pr18033.
------------------------------------------------------------------------

llvm-svn: 196057
parent c1645f97
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -5776,6 +5776,8 @@ public:
  // C++ Template Argument Deduction (C++ [temp.deduct])
  //===--------------------------------------------------------------------===//

  QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType);

  /// \brief Describes the result of template argument deduction.
  ///
  /// The TemplateDeductionResult enumeration describes the result of
+2 −1
Original line number Diff line number Diff line
@@ -7441,7 +7441,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
    NamedDecl *Prev = *P;
    if (!HasExplicitTemplateArgs) {
      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
        if (Context.hasSameUnqualifiedType(Method->getType(), R)) {
        QualType Adjusted = adjustCCAndNoReturn(R, Method->getType());
        if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
          Matches.clear();

          Matches.addDecl(Method, P.getAccess());
+24 −17
Original line number Diff line number Diff line
@@ -3501,6 +3501,28 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
                                         Specialization, Info, &OriginalCallArgs);
}

QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
                                   QualType FunctionType) {
  if (ArgFunctionType.isNull())
    return ArgFunctionType;

  const FunctionProtoType *FunctionTypeP =
      FunctionType->castAs<FunctionProtoType>();
  CallingConv CC = FunctionTypeP->getCallConv();
  bool NoReturn = FunctionTypeP->getNoReturnAttr();
  const FunctionProtoType *ArgFunctionTypeP =
      ArgFunctionType->getAs<FunctionProtoType>();
  if (ArgFunctionTypeP->getCallConv() == CC &&
      ArgFunctionTypeP->getNoReturnAttr() == NoReturn)
    return ArgFunctionType;

  FunctionType::ExtInfo EI = ArgFunctionTypeP->getExtInfo().withCallingConv(CC);
  EI = EI.withNoReturn(NoReturn);
  ArgFunctionTypeP =
      cast<FunctionProtoType>(Context.adjustFunctionType(ArgFunctionTypeP, EI));
  return QualType(ArgFunctionTypeP, 0);
}

/// \brief Deduce template arguments when taking the address of a function
/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to
/// a template.
@@ -3538,23 +3560,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
  TemplateParameterList *TemplateParams
    = FunctionTemplate->getTemplateParameters();
  QualType FunctionType = Function->getType();
  if (!InOverloadResolution && !ArgFunctionType.isNull()) {
    const FunctionProtoType *FunctionTypeP =
        FunctionType->castAs<FunctionProtoType>();
    CallingConv CC = FunctionTypeP->getCallConv();
    bool NoReturn = FunctionTypeP->getNoReturnAttr();
    const FunctionProtoType *ArgFunctionTypeP =
        ArgFunctionType->getAs<FunctionProtoType>();
    if (ArgFunctionTypeP->getCallConv() != CC ||
        ArgFunctionTypeP->getNoReturnAttr() != NoReturn) {
      FunctionType::ExtInfo EI =
          ArgFunctionTypeP->getExtInfo().withCallingConv(CC);
      EI = EI.withNoReturn(NoReturn);
      ArgFunctionTypeP = cast<FunctionProtoType>(
          Context.adjustFunctionType(ArgFunctionTypeP, EI));
      ArgFunctionType = QualType(ArgFunctionTypeP, 0);
    }
  }
  if (!InOverloadResolution)
    ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType);

  // Substitute any explicit template arguments.
  LocalInstantiationScope InstScope(*this);
+8 −0
Original line number Diff line number Diff line
@@ -183,3 +183,11 @@ namespace test4 {
  };
  extern template void foo::bar(const void *);
}

namespace test5 {
  template <class T>
  class valarray {
    void bar();
  };
  extern template void valarray<int>::bar();
}