summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Sema.h3
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp7
-rw-r--r--clang/lib/Sema/SemaType.cpp61
-rw-r--r--clang/test/SemaCXX/auto-cxx0x.cpp7
4 files changed, 44 insertions, 34 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1645b4d439d..dc2947f587e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6727,6 +6727,9 @@ public:
/// \brief Substitute Replacement for auto in TypeWithAuto
TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
QualType Replacement);
+ /// \brief Completely replace the \c auto in \p TypeWithAuto by
+ /// \p Replacement. This does not retain any \c auto type sugar.
+ QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement);
/// \brief Result type of DeduceAutoType.
enum DeduceAutoResult {
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 688d6bb8e68..57957c0728a 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -4250,6 +4250,13 @@ TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
.TransformType(TypeWithAuto);
}
+QualType Sema::ReplaceAutoType(QualType TypeWithAuto,
+ QualType TypeToReplaceAuto) {
+ return SubstituteAutoTransform(*this, TypeToReplaceAuto,
+ /*UseAutoSugar*/ false)
+ .TransformType(TypeWithAuto);
+}
+
void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
if (isa<InitListExpr>(Init))
Diag(VDecl->getLocation(),
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 92a2ecc2275..a59511ca77e 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1502,40 +1502,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
break;
case DeclSpec::TST_auto:
- // TypeQuals handled by caller.
- // If auto is mentioned in a lambda parameter context, convert it to a
- // template parameter type immediately, with the appropriate depth and
- // index, and update sema's state (LambdaScopeInfo) for the current lambda
- // being analyzed (which tracks the invented type template parameter).
- if (declarator.getContext() == Declarator::LambdaExprParameterContext) {
- sema::LambdaScopeInfo *LSI = S.getCurLambda();
- assert(LSI && "No LambdaScopeInfo on the stack!");
- const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
- const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
- const bool IsParameterPack = declarator.hasEllipsis();
-
- // Turns out we must create the TemplateTypeParmDecl here to
- // retrieve the corresponding template parameter type.
- TemplateTypeParmDecl *CorrespondingTemplateParam =
- TemplateTypeParmDecl::Create(Context,
- // Temporarily add to the TranslationUnit DeclContext. When the
- // associated TemplateParameterList is attached to a template
- // declaration (such as FunctionTemplateDecl), the DeclContext
- // for each template parameter gets updated appropriately via
- // a call to AdoptTemplateParameterList.
- Context.getTranslationUnitDecl(),
- /*KeyLoc*/ SourceLocation(),
- /*NameLoc*/ declarator.getLocStart(),
- TemplateParameterDepth,
- AutoParameterPosition, // our template param index
- /* Identifier*/ nullptr, false, IsParameterPack);
- LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
- // Replace the 'auto' in the function parameter with this invented
- // template type parameter.
- Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);
- } else {
- Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
- }
+ Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
break;
case DeclSpec::TST_auto_type:
@@ -2802,6 +2769,32 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
if (!SemaRef.getLangOpts().CPlusPlus14 ||
!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
Error = 16;
+ else {
+ // If auto is mentioned in a lambda parameter context, convert it to a
+ // template parameter type.
+ sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda();
+ assert(LSI && "No LambdaScopeInfo on the stack!");
+ const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
+ const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
+ const bool IsParameterPack = D.hasEllipsis();
+
+ // Create the TemplateTypeParmDecl here to retrieve the corresponding
+ // template parameter type. Template parameters are temporarily added
+ // to the TU until the associated TemplateDecl is created.
+ TemplateTypeParmDecl *CorrespondingTemplateParam =
+ TemplateTypeParmDecl::Create(
+ SemaRef.Context, SemaRef.Context.getTranslationUnitDecl(),
+ /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(),
+ TemplateParameterDepth, AutoParameterPosition,
+ /*Identifier*/nullptr, false, IsParameterPack);
+ LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
+ // Replace the 'auto' in the function parameter with this invented
+ // template type parameter.
+ // FIXME: Retain some type sugar to indicate that this was written
+ // as 'auto'.
+ T = SemaRef.ReplaceAutoType(
+ T, QualType(CorrespondingTemplateParam->getTypeForDecl(), 0));
+ }
break;
case Declarator::MemberContext: {
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
diff --git a/clang/test/SemaCXX/auto-cxx0x.cpp b/clang/test/SemaCXX/auto-cxx0x.cpp
index c37b1386b3a..074a01bb839 100644
--- a/clang/test/SemaCXX/auto-cxx0x.cpp
+++ b/clang/test/SemaCXX/auto-cxx0x.cpp
@@ -8,3 +8,10 @@ void f() {
typedef auto PR25449(); // expected-error {{'auto' not allowed in typedef}}
thread_local auto x; // expected-error {{requires an initializer}}
+
+void g() {
+ [](auto){}(0);
+#if __cplusplus == 201103L
+ // expected-error@-2 {{'auto' not allowed in lambda parameter}}
+#endif
+}
OpenPOWER on IntegriCloud