Index: include/clang/AST/Decl.h =================================================================== --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -715,7 +715,8 @@ enum InitializationStyle { CInit, ///< C-style initialization with assignment CallInit, ///< Call-style initialization (C++98) - ListInit ///< Direct list-initialization (C++11) + ListInit, ///< Direct list-initialization (C++11) + MagicInit ///< Call-style init without access checking }; /// \brief Kinds of thread-local storage. @@ -1147,7 +1148,8 @@ bool checkInitIsICE() const; void setInitStyle(InitializationStyle Style) { - VarDeclBits.InitStyle = Style; + if (getInitStyle() != MagicInit) + VarDeclBits.InitStyle = Style; } /// \brief The style of initialization for this declaration. Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -1697,6 +1697,10 @@ "array backing the initializer list will be destroyed at the end of " "%select{the full-expression|the constructor}0">, InGroup>; +def err_implied_std_arb_not_found : Error< + "cannot deduce type of array because std::arb was not found">; +def err_malformed_std_arb : Error< + "std::arb must be a class template with a single type parameter">; // C++1y decltype(auto) type def err_decltype_auto_cannot_be_combined : Error< Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -167,6 +167,7 @@ LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators") LANGOPT(SizedDeallocation , 1, 0, "enable sized deallocation functions") +LANGOPT(FancyARBs , 1, 0, "use std::arb to represent ARBs") BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision") BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records") BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form") Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -849,6 +849,9 @@ def fsized_deallocation : Flag<["-"], "fsized-deallocation">, Flags<[CC1Option]>, HelpText<"Enable C++14 sized global deallocation functions">, Group; def fno_sized_deallocation: Flag<["-"], "fno-sized-deallocation">, Group; +def ffancy_arbs : Flag<["-"], "ffancy-arbs">, Flags<[CC1Option]>, + HelpText<"Use std::arb for ARBs">, Group; +def fno_fancy_arbs: Flag<["-"], "fno-fancy-arbs">, Group; def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group, Flags<[CC1Option]>, HelpText<"Use GC exclusively for Objective-C related memory management">; Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -1726,11 +1726,11 @@ DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, SourceLocation *DeclEnd = nullptr, ForRangeInit *FRI = nullptr); - Decl *ParseDeclarationAfterDeclarator(Declarator &D, + Decl *ParseDeclarationAfterDeclarator(Declarator &D, Decl *&AuxDecl, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); bool ParseAsmAttributesAfterDeclarator(Declarator &D); Decl *ParseDeclarationAfterDeclaratorAndAttributes( - Declarator &D, + Declarator &D, Decl *&AuxDecl, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), ForRangeInit *FRI = nullptr); Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope); Index: include/clang/Sema/Initialization.h =================================================================== --- include/clang/Sema/Initialization.h +++ include/clang/Sema/Initialization.h @@ -918,7 +918,8 @@ const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - QualType *ResultType = nullptr); + QualType *ResultType = nullptr, + bool NoAccessCheck = false); /// \brief Diagnose an potentially-invalid initialization sequence. /// Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -629,6 +629,9 @@ /// \. ClassTemplateDecl *StdInitializerList; + /// \brief The C++ "std::arb" template, which is defined in \. + ClassTemplateDecl *StdARB; + /// \brief The C++ "type_info" declaration, which is defined in \. RecordDecl *CXXTypeInfoDecl; @@ -1499,9 +1502,13 @@ std::unique_ptr CCC = nullptr); Decl *ActOnDeclarator(Scope *S, Declarator &D); + Decl *ActOnDeclarator(Scope *S, Declarator &D, Decl *&AuxDecl); NamedDecl *HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists); + NamedDecl *HandleDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, + Decl *&AuxDecl); void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S); bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info); bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, @@ -1533,7 +1540,7 @@ TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, - bool &AddToScope); + bool &AddToScope, Decl *&AuxDecl); // Returns true if the variable declaration is a redeclaration bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous); void CheckVariableDeclarationType(VarDecl *NewVD); @@ -3912,6 +3919,12 @@ /// defined in [dcl.init.list]p2. bool isInitListConstructor(const CXXConstructorDecl *Ctor); + /// \brief Looks for the std::arb template and instantiates it + /// with Element, or emits an error if it's not found. + /// + /// \returns The instantiated template, or null on error. + QualType BuildStdARB(QualType Element, SourceLocation Loc); + Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc, SourceLocation NamespcLoc, Index: lib/AST/ASTDumper.cpp =================================================================== --- lib/AST/ASTDumper.cpp +++ lib/AST/ASTDumper.cpp @@ -1154,6 +1154,7 @@ case VarDecl::CInit: OS << " cinit"; break; case VarDecl::CallInit: OS << " callinit"; break; case VarDecl::ListInit: OS << " listinit"; break; + case VarDecl::MagicInit: OS << " magicinit"; break; } dumpStmt(D->getInit()); } Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -4351,6 +4351,11 @@ options::OPT_fno_sized_deallocation, false)) CmdArgs.push_back("-fsized-deallocation"); + // Should we use std::arb for ARBs? + if (Args.hasFlag(options::OPT_ffancy_arbs, + options::OPT_fno_fancy_arbs, false)) + CmdArgs.push_back("-ffancy-arbs"); + // -fconstant-cfstrings is default, and may be subject to argument translation // on Darwin. if (!Args.hasFlag(options::OPT_fconstant_cfstrings, Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1535,6 +1535,7 @@ Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin); Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation); + Opts.FancyARBs = Args.hasArg(OPT_ffancy_arbs); Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); Opts.AccessControl = !Args.hasArg(OPT_fno_access_control); Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); Index: lib/Frontend/InitPreprocessor.cpp =================================================================== --- lib/Frontend/InitPreprocessor.cpp +++ lib/Frontend/InitPreprocessor.cpp @@ -929,6 +929,9 @@ InitializeStandardPredefinedMacros(PP.getTargetInfo(), PP.getLangOpts(), FEOpts, Builder); + if (InitOpts.UsePredefines && LangOpts.FancyARBs) + AddImplicitInclude(Builder, "__arb.h"); + // Add on the predefines from the driver. Wrap in a #line directive to report // that they come from the command line. if (!PP.getLangOpts().AsmPreprocessor) Index: lib/Headers/CMakeLists.txt =================================================================== --- lib/Headers/CMakeLists.txt +++ lib/Headers/CMakeLists.txt @@ -2,6 +2,7 @@ adxintrin.h altivec.h ammintrin.h + __arb.h arm_acle.h avx2intrin.h avx512bwintrin.h Index: lib/Headers/__arb.h =================================================================== --- /dev/null +++ lib/Headers/__arb.h @@ -0,0 +1,74 @@ +// -*- C++ -*- +//===----------------------------- arb ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef _ARB +#define _ARB + +#pragma GCC system_header + +namespace std { inline namespace __clang_arb_v1 { + +template +struct arb final +{ +public: + typedef _Tp value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef __SIZE_TYPE__ size_type; + typedef __PTRDIFF_TYPE__ difference_type; + +public: + arb(arb&&) = delete; + arb(const arb&) = delete; + arb& operator=(const arb&) = delete; + +private: + value_type * __base_; + size_type __size_; + +private: + arb(pointer __p, size_type __s) noexcept : __base_(__p), __size_(__s) {} + +public: + inline iterator begin() noexcept { return iterator(data()); } + inline const_iterator begin() const noexcept { return const_iterator(data()); } + inline const_iterator cbegin() const noexcept { return const_iterator(data()); } + inline iterator end() noexcept { return iterator(data() + __size_); } + inline const_iterator end() const noexcept { return const_iterator(data() + __size_); } + inline const_iterator cend() const noexcept { return const_iterator(data() + __size_); } + + inline size_type size() const noexcept { return __size_; } + inline size_type max_size() const noexcept { return __size_; } + inline bool empty() const noexcept { return __size_ == 0; } + + inline reference operator[](size_type __n) { return data()[__n]; } + inline const_reference operator[](size_type __n) const { return data()[__n]; } + + inline reference front() { return data()[0]; } + inline const_reference front() const { return data()[0]; } + inline reference back() { return data()[__size_-1]; } + inline const_reference back() const { return data()[__size_-1]; } + + inline _Tp* data() noexcept { return __base_; } + inline const _Tp* data() const noexcept { return __base_; } + + inline operator _Tp*() noexcept { return data(); } + inline operator const _Tp*() const noexcept { return data(); } +}; + +}} + +#endif // _ARB + Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -1779,11 +1779,14 @@ } SmallVector DeclsInGroup; + Decl *AuxDecl = nullptr; Decl *FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes( - D, ParsedTemplateInfo(), FRI); + D, AuxDecl, ParsedTemplateInfo(), FRI); if (LateParsedAttrs.size() > 0) ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false); D.complete(FirstDecl); + if (AuxDecl) + DeclsInGroup.push_back(AuxDecl); if (FirstDecl) DeclsInGroup.push_back(FirstDecl); @@ -1822,8 +1825,11 @@ ParseDeclarator(D); if (!D.isInvalidType()) { - Decl *ThisDecl = ParseDeclarationAfterDeclarator(D); + Decl *AuxDecl = nullptr; + Decl *ThisDecl = ParseDeclarationAfterDeclarator(D, AuxDecl); D.complete(ThisDecl); + if (AuxDecl) + DeclsInGroup.push_back(AuxDecl); if (ThisDecl) DeclsInGroup.push_back(ThisDecl); } @@ -1891,20 +1897,21 @@ /// definitions, but that definitely doesn't fit with the parser here. /// Decl *Parser::ParseDeclarationAfterDeclarator( - Declarator &D, const ParsedTemplateInfo &TemplateInfo) { + Declarator &D, Decl *&AuxDecl, const ParsedTemplateInfo &TemplateInfo) { if (ParseAsmAttributesAfterDeclarator(D)) return nullptr; - return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo); + return ParseDeclarationAfterDeclaratorAndAttributes(D, AuxDecl, TemplateInfo); } Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( - Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) { + Declarator &D, Decl *&AuxDecl, const ParsedTemplateInfo &TemplateInfo, + ForRangeInit *FRI) { // Inform the current actions module that we just parsed this declarator. Decl *ThisDecl = nullptr; switch (TemplateInfo.Kind) { case ParsedTemplateInfo::NonTemplate: - ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); + ThisDecl = Actions.ActOnDeclarator(getCurScope(), D, AuxDecl); break; case ParsedTemplateInfo::Template: @@ -2087,7 +2094,10 @@ Actions.AddInitializerToDecl(ThisDecl, Init.get(), /*DirectInit=*/true, TypeContainsAuto); - } else { + } else if (!(ThisDecl && isa(ThisDecl) && + cast(ThisDecl)->hasInit())) { + // Sema might have added an implicit initializer, but if not, this is an + // uninitialized decl. Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto); } Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -283,8 +283,10 @@ } // Parse this declaration. - Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo, + Decl *AuxDecl = nullptr; + Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo, AuxDecl, TemplateInfo); + assert(!AuxDecl && "Should not have an aux decl here!"); if (Tok.is(tok::comma)) { Diag(Tok, diag::err_multiple_template_declarators) Index: lib/Sema/JumpDiagnostics.cpp =================================================================== --- lib/Sema/JumpDiagnostics.cpp +++ lib/Sema/JumpDiagnostics.cpp @@ -184,7 +184,8 @@ if (const CXXConstructExpr *CCE = dyn_cast(Init)) { const CXXConstructorDecl *Ctor = CCE->getConstructor(); if (Ctor->isTrivial() && Ctor->isDefaultConstructor() && - VD->getInitStyle() == VarDecl::CallInit) { + (VD->getInitStyle() == VarDecl::CallInit || + VD->getInitStyle() == VarDecl::MagicInit)) { if (OutDiag) InDiag = diag::note_protected_by_variable_nontriv_destructor; else if (!Ctor->getParent()->isPOD()) Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -90,7 +90,7 @@ ExprNeedsCleanups(false), LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr), - CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), + StdARB(nullptr), CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), NSNumberDecl(nullptr), NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr), Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -4478,8 +4478,16 @@ } Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { + Decl *AuxDecl = nullptr; + Decl *Result = ActOnDeclarator(S, D, AuxDecl); + assert(!AuxDecl && "aux decl not expected here!"); + + return Result; +} + +Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D, Decl *&AuxDecl) { D.setFunctionDefinitionKind(FDK_Declaration); - Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg()); + Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg(), AuxDecl); if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() && Dcl && Dcl->getDeclContext()->isFileContext()) @@ -4605,6 +4613,16 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists) { + Decl *AuxDecl = nullptr; + NamedDecl *ND = HandleDeclarator(S, D, TemplateParamLists, AuxDecl); + assert(!AuxDecl && "aux decl not expected here"); + + return ND; +} + +NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParamLists, + Decl *&AuxDecl) { // TODO: consider using NameInfo for diagnostic. DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); @@ -4794,7 +4812,7 @@ AddToScope); } else { New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, TemplateParamLists, - AddToScope); + AddToScope, AuxDecl); } if (!New) @@ -5461,11 +5479,60 @@ return true; } +static ClassTemplateDecl *LookupStdARB(Sema &S, SourceLocation Loc){ + NamespaceDecl *Std = S.getStdNamespace(); + if (!Std) { + S.Diag(Loc, diag::err_implied_std_arb_not_found); + return nullptr; + } + + LookupResult Result(S, &S.PP.getIdentifierTable().get("arb"), + Loc, Sema::LookupOrdinaryName); + if (!S.LookupQualifiedName(Result, Std)) { + S.Diag(Loc, diag::err_implied_std_arb_not_found); + return nullptr; + } + ClassTemplateDecl *Template = Result.getAsSingle(); + if (!Template) { + Result.suppressDiagnostics(); + // We found something weird. Complain about the first thing we found. + NamedDecl *Found = *Result.begin(); + S.Diag(Found->getLocation(), diag::err_malformed_std_arb); + return nullptr; + } + + // We found some template called std::arb. Now verify that it's + // correct. + TemplateParameterList *Params = Template->getTemplateParameters(); + if (Params->getMinRequiredArguments() != 1 || + !isa(Params->getParam(0))) { + S.Diag(Template->getLocation(), diag::err_malformed_std_arb); + return nullptr; + } + + return Template; +} + +QualType Sema::BuildStdARB(QualType Element, SourceLocation Loc) { + if (!StdARB) { + StdARB = LookupStdARB(*this, Loc); + if (!StdARB) + return QualType(); + } + + TemplateArgumentListInfo Args(Loc, Loc); + Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element), + Context.getTrivialTypeSourceInfo(Element, + Loc))); + return Context.getCanonicalType( + CheckTemplateIdType(TemplateName(StdARB), Loc, Args)); +} + NamedDecl * Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, - bool &AddToScope) { + bool &AddToScope, Decl *&AuxDecl) { QualType R = TInfo->getType(); DeclarationName Name = GetNameForDeclarator(D).getName(); @@ -5704,6 +5771,62 @@ return nullptr; NewVD = cast(Res.get()); AddToScope = false; + } else if (getLangOpts().FancyARBs && R->isVariableArrayType()) { + // If we're using fancy ARBs, create a std::arb object for an ARB instead + // of a VLA. + const VariableArrayType *VAT = Context.getAsVariableArrayType(R); + QualType ARBTy = BuildStdARB(VAT->getElementType(), D.getLocStart()); + if (!ARBTy.isNull()) { + // To get the pointer, we'll create an underlying VLA (this VLA will + // actually own the memory and be responsible for managing the lifetime + // of the contained objects). + UnqualifiedId ARBName; + ARBName.setIdentifier(PP.getIdentifierInfo(Name.getAsString() + ".ARB"), + D.getIdentifierLoc()); + VarDecl *ARBVD = + VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), + PP.getIdentifierInfo(Name.getAsString() + ".ARB"), + R, TInfo, SC); + ARBVD->setImplicit(); + ActOnUninitializedDecl(ARBVD, + D.getDeclSpec().containsPlaceholderType()); + FinalizeDeclaration(ARBVD); + + ARBVD->setReferenced(); + ARBVD->markUsed(Context); + + // This must also be attached to the parent group. + AuxDecl = ARBVD; + + ExprResult ARBExpRef = BuildDeclRefExpr(ARBVD, R, VK_LValue, + D.getIdentifierLoc(), + &D.getCXXScopeSpec()); + + R = ARBTy; + TInfo = Context.getTrivialTypeSourceInfo(R); + + NewVD = VarDecl::Create(Context, DC, D.getLocStart(), + D.getIdentifierLoc(), II, R, TInfo, SC); + + // We're going to call a private constructor of std::arb. + NewVD->setInitStyle(VarDecl::MagicInit); + + Expr *NumElementsExpr = VAT->getSizeExpr(); + + // We need to pass to the constructor a pointer to the allocated memory + // and the number of allocated elements. + SmallVector Exprs(1, ARBExpRef.get()); + + // The second parameter is the size. + Exprs.push_back(NumElementsExpr); + + ExprResult Initializer = + ActOnParenListExpr(D.getLocStart(), SourceLocation(), Exprs); + AddInitializerToDecl(NewVD, Initializer.get(), /*DirectInit=*/true, + D.getDeclSpec().containsPlaceholderType()); + } else + NewVD = VarDecl::Create(Context, DC, D.getLocStart(), + D.getIdentifierLoc(), II, R, TInfo, SC); } else NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, R, TInfo, SC); @@ -8980,7 +9103,9 @@ return; InitializationSequence InitSeq(*this, Entity, Kind, Args); - ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT); + bool NoAccessCheck = VDecl->getInitStyle() == VarDecl::MagicInit; + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT, + NoAccessCheck); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -5391,6 +5391,7 @@ bool &ConstructorInitRequiresZeroInit, bool IsListInitialization, bool IsStdInitListInitialization, + bool NoAccessCheck, SourceLocation LBraceLoc, SourceLocation RBraceLoc) { unsigned NumArgs = Args.size(); @@ -5500,8 +5501,9 @@ return ExprError(); // Only check access if all of that succeeded. - S.CheckConstructorAccess(Loc, Constructor, Entity, - Step.Function.FoundDecl.getAccess()); + if (!NoAccessCheck) + S.CheckConstructorAccess(Loc, Constructor, Entity, + Step.Function.FoundDecl.getAccess()); if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc)) return ExprError(); @@ -5879,7 +5881,7 @@ const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, - QualType *ResultType) { + QualType *ResultType, bool NoAccessCheck) { if (Failed()) { Diagnose(S, Entity, Kind, Args); return ExprError(); @@ -6378,6 +6380,7 @@ ConstructorInitRequiresZeroInit, /*IsListInitialization*/true, /*IsStdInitListInit*/false, + NoAccessCheck, InitList->getLBraceLoc(), InitList->getRBraceLoc()); break; @@ -6417,6 +6420,7 @@ ConstructorInitRequiresZeroInit, /*IsListInitialization*/IsStdInitListInit, /*IsStdInitListInitialization*/IsStdInitListInit, + /*NoAccessCheck*/NoAccessCheck, /*LBraceLoc*/SourceLocation(), /*RBraceLoc*/SourceLocation()); break; Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3694,7 +3694,8 @@ // Instantiate the initializer. ExprResult Init = SubstInitializer(OldVar->getInit(), TemplateArgs, - OldVar->getInitStyle() == VarDecl::CallInit); + OldVar->getInitStyle() == VarDecl::CallInit || + OldVar->getInitStyle() == VarDecl::MagicInit); if (!Init.isInvalid()) { bool TypeMayContainAuto = true; Expr *InitExpr = Init.get(); Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -9139,7 +9139,8 @@ Sema::PotentiallyEvaluated); ExprResult NewExprInitResult = getDerived().TransformInitializer( C->getCapturedVar()->getInit(), - C->getCapturedVar()->getInitStyle() == VarDecl::CallInit); + C->getCapturedVar()->getInitStyle() == VarDecl::CallInit || + C->getCapturedVar()->getInitStyle() == VarDecl::MagicInit); if (NewExprInitResult.isInvalid()) return ExprError(); Index: test/CodeGen/fancy-arbs.cpp =================================================================== --- /dev/null +++ test/CodeGen/fancy-arbs.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++14 -ffancy-arbs -emit-llvm -o - %s | FileCheck %s + +void bar(int *) { +} + +template +int car(const T& c) { + return c.size(); +} + +void foo(int n) { + int q[n]; + bar(q); + car(q); + +// CHECK-LABEL: define void @_Z3fooi +// CHECK: [[ARB:%[0-9a-z]+]] = alloca %"struct.std::__clang_arb_v1::arb" +// CHECK: [[VLA:%[0-9a-z]+]] = alloca i32, i64 %{{.*}} +// CHECK: call void @_ZNSt14__clang_arb_v13arbIiEC1EPim(%"struct.std::__clang_arb_v1::arb"* [[ARB]], i32* [[VLA]] +// CHECK: [[ARBP:%[0-9a-z]+]] = call i32* @_ZNSt14__clang_arb_v13arbIiEcvPiEv(%"struct.std::__clang_arb_v1::arb"* [[ARB]]) +// CHECK: call void @_Z3barPi(i32* [[ARBP]]) +// CHECK: call{{.*}} @_Z3carINSt14__clang_arb_v13arbIiEEEiRKT_(%"struct.std::__clang_arb_v1::arb"* dereferenceable({{[0-9]+}}) [[ARB]] +} + +template +void too(int n) { + T q[n]; + bar(q); + car(q); +} + +// CHECK-LABEL: define linkonce_odr void @_Z3tooIiEvi +// CHECK: [[ARB:%[0-9a-z]+]] = alloca %"struct.std::__clang_arb_v1::arb" +// CHECK: [[VLA:%[0-9a-z]+]] = alloca i32, i64 %{{.*}} +// CHECK: call void @_ZNSt14__clang_arb_v13arbIiEC1EPim(%"struct.std::__clang_arb_v1::arb"* [[ARB]], i32* [[VLA]] +// CHECK: [[ARBP:%[0-9a-z]+]] = call i32* @_ZNSt14__clang_arb_v13arbIiEcvPiEv(%"struct.std::__clang_arb_v1::arb"* [[ARB]]) +// CHECK: call void @_Z3barPi(i32* [[ARBP]]) +// CHECK: call{{.*}} @_Z3carINSt14__clang_arb_v13arbIiEEEiRKT_(%"struct.std::__clang_arb_v1::arb"* dereferenceable({{[0-9]+}}) [[ARB]] + +void hello(int size) { + foo(size); + too(size); +} +