Vendor import of clang release_60 branch r325330:
https://llvm.org/svn/llvm-project/cfe/branches/release_60@325330
This commit is contained in:
parent
660d91aa9e
commit
6eea8b8c1a
@ -132,6 +132,11 @@ New Compiler Flags
|
||||
difference between the ``-std=c17`` and ``-std=c11`` language modes is the
|
||||
value of the ``__STDC_VERSION__`` macro, as C17 is a bug fix release.
|
||||
|
||||
- Added the ``-fexperimental-isel`` and ``-fno-experimental-isel`` flags to
|
||||
enable/disable the new GlobalISel instruction selection framework. This
|
||||
feature is enabled by default for AArch64 at the ``-O0`` optimization level.
|
||||
Support for other targets or optimization levels is currently incomplete.
|
||||
|
||||
Deprecated Compiler Flags
|
||||
-------------------------
|
||||
|
||||
|
@ -836,6 +836,10 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl {
|
||||
|
||||
void setLexicalDeclContext(DeclContext *DC);
|
||||
|
||||
/// Determine whether this declaration is a templated entity (whether it is
|
||||
// within the scope of a template parameter).
|
||||
bool isTemplated() const;
|
||||
|
||||
/// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
|
||||
/// scoped decl is defined outside the current function or method. This is
|
||||
/// roughly global variables and functions, but also handles enums (which
|
||||
|
@ -2145,7 +2145,7 @@ static bool unionHasUniqueObjectRepresentations(const ASTContext &Context,
|
||||
if (FieldSize != UnionSize)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return !RD->field_empty();
|
||||
}
|
||||
|
||||
static bool isStructEmpty(QualType Ty) {
|
||||
|
@ -236,10 +236,23 @@ TemplateDecl *Decl::getDescribedTemplate() const {
|
||||
return RD->getDescribedClassTemplate();
|
||||
else if (auto *VD = dyn_cast<VarDecl>(this))
|
||||
return VD->getDescribedVarTemplate();
|
||||
else if (auto *AD = dyn_cast<TypeAliasDecl>(this))
|
||||
return AD->getDescribedAliasTemplate();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Decl::isTemplated() const {
|
||||
// A declaration is dependent if it is a template or a template pattern, or
|
||||
// is within (lexcially for a friend, semantically otherwise) a dependent
|
||||
// context.
|
||||
// FIXME: Should local extern declarations be treated like friends?
|
||||
if (auto *AsDC = dyn_cast<DeclContext>(this))
|
||||
return AsDC->isDependentContext();
|
||||
auto *DC = getFriendObjectKind() ? getLexicalDeclContext() : getDeclContext();
|
||||
return DC->isDependentContext() || isTemplateDecl() || getDescribedTemplate();
|
||||
}
|
||||
|
||||
const DeclContext *Decl::getParentFunctionOrMethod() const {
|
||||
for (const DeclContext *DC = getDeclContext();
|
||||
DC && !DC->isTranslationUnit() && !DC->isNamespace();
|
||||
|
@ -950,11 +950,10 @@ void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
|
||||
}
|
||||
}
|
||||
|
||||
// <postfix> ::= <unqualified-name> [<postfix>]
|
||||
// ::= <substitution> [<postfix>]
|
||||
void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
|
||||
// <postfix> ::= <unqualified-name> [<postfix>]
|
||||
// ::= <substitution> [<postfix>]
|
||||
const DeclContext *DC = getEffectiveDeclContext(ND);
|
||||
|
||||
while (!DC->isTranslationUnit()) {
|
||||
if (isa<TagDecl>(ND) || isa<VarDecl>(ND)) {
|
||||
unsigned Disc;
|
||||
@ -2140,6 +2139,7 @@ void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
|
||||
case CC_X86StdCall: Out << 'G'; break;
|
||||
case CC_X86FastCall: Out << 'I'; break;
|
||||
case CC_X86VectorCall: Out << 'Q'; break;
|
||||
case CC_Swift: Out << 'S'; break;
|
||||
case CC_X86RegCall: Out << 'w'; break;
|
||||
}
|
||||
}
|
||||
|
@ -4000,18 +4000,13 @@ void CodeGenModule::EmitDeclContext(const DeclContext *DC) {
|
||||
/// EmitTopLevelDecl - Emit code for a single top level declaration.
|
||||
void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
||||
// Ignore dependent declarations.
|
||||
if (D->getDeclContext() && D->getDeclContext()->isDependentContext())
|
||||
if (D->isTemplated())
|
||||
return;
|
||||
|
||||
switch (D->getKind()) {
|
||||
case Decl::CXXConversion:
|
||||
case Decl::CXXMethod:
|
||||
case Decl::Function:
|
||||
// Skip function templates
|
||||
if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() ||
|
||||
cast<FunctionDecl>(D)->isLateTemplateParsed())
|
||||
return;
|
||||
|
||||
EmitGlobal(cast<FunctionDecl>(D));
|
||||
// Always provide some coverage mapping
|
||||
// even for the functions that aren't emitted.
|
||||
@ -4024,10 +4019,6 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
||||
|
||||
case Decl::Var:
|
||||
case Decl::Decomposition:
|
||||
// Skip variable templates
|
||||
if (cast<VarDecl>(D)->getDescribedVarTemplate())
|
||||
return;
|
||||
LLVM_FALLTHROUGH;
|
||||
case Decl::VarTemplateSpecialization:
|
||||
EmitGlobal(cast<VarDecl>(D));
|
||||
if (auto *DD = dyn_cast<DecompositionDecl>(D))
|
||||
@ -4086,16 +4077,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
||||
DI->EmitUsingDirective(cast<UsingDirectiveDecl>(*D));
|
||||
return;
|
||||
case Decl::CXXConstructor:
|
||||
// Skip function templates
|
||||
if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate() ||
|
||||
cast<FunctionDecl>(D)->isLateTemplateParsed())
|
||||
return;
|
||||
|
||||
getCXXABI().EmitCXXConstructors(cast<CXXConstructorDecl>(D));
|
||||
break;
|
||||
case Decl::CXXDestructor:
|
||||
if (cast<FunctionDecl>(D)->isLateTemplateParsed())
|
||||
return;
|
||||
getCXXABI().EmitCXXDestructors(cast<CXXDestructorDecl>(D));
|
||||
break;
|
||||
|
||||
|
@ -2761,6 +2761,11 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
|
||||
// N.B. We must always emit the RTTI data ourselves if there exists a key
|
||||
// function.
|
||||
bool IsDLLImport = RD->hasAttr<DLLImportAttr>();
|
||||
|
||||
// Don't import the RTTI but emit it locally.
|
||||
if (CGM.getTriple().isWindowsGNUEnvironment() && IsDLLImport)
|
||||
return false;
|
||||
|
||||
if (CGM.getVTables().isVTableExternal(RD))
|
||||
return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment()
|
||||
? false
|
||||
|
@ -3543,7 +3543,17 @@ ABIArgInfo X86_64ABIInfo::classifyRegCallStructType(QualType Ty,
|
||||
|
||||
void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI) const {
|
||||
|
||||
bool IsRegCall = FI.getCallingConvention() == llvm::CallingConv::X86_RegCall;
|
||||
const unsigned CallingConv = FI.getCallingConvention();
|
||||
// It is possible to force Win64 calling convention on any x86_64 target by
|
||||
// using __attribute__((ms_abi)). In such case to correctly emit Win64
|
||||
// compatible code delegate this call to WinX86_64ABIInfo::computeInfo.
|
||||
if (CallingConv == llvm::CallingConv::Win64) {
|
||||
WinX86_64ABIInfo Win64ABIInfo(CGT);
|
||||
Win64ABIInfo.computeInfo(FI);
|
||||
return;
|
||||
}
|
||||
|
||||
bool IsRegCall = CallingConv == llvm::CallingConv::X86_RegCall;
|
||||
|
||||
// Keep track of the number of assigned registers.
|
||||
unsigned FreeIntRegs = IsRegCall ? 11 : 6;
|
||||
|
@ -1723,15 +1723,18 @@ void TokenAnnotator::setCommentLineLevels(
|
||||
}
|
||||
}
|
||||
|
||||
if (NextNonCommentLine && CommentLine) {
|
||||
// If the comment is currently aligned with the line immediately following
|
||||
// it, that's probably intentional and we should keep it.
|
||||
bool AlignedWithNextLine =
|
||||
NextNonCommentLine->First->NewlinesBefore <= 1 &&
|
||||
NextNonCommentLine->First->OriginalColumn ==
|
||||
(*I)->First->OriginalColumn;
|
||||
if (AlignedWithNextLine)
|
||||
(*I)->Level = NextNonCommentLine->Level;
|
||||
// If the comment is currently aligned with the line immediately following
|
||||
// it, that's probably intentional and we should keep it.
|
||||
if (NextNonCommentLine && CommentLine &&
|
||||
NextNonCommentLine->First->NewlinesBefore <= 1 &&
|
||||
NextNonCommentLine->First->OriginalColumn ==
|
||||
(*I)->First->OriginalColumn) {
|
||||
// Align comments for preprocessor lines with the # in column 0.
|
||||
// Otherwise, align with the next line.
|
||||
(*I)->Level = (NextNonCommentLine->Type == LT_PreprocessorDirective ||
|
||||
NextNonCommentLine->Type == LT_ImportStatement)
|
||||
? 0
|
||||
: NextNonCommentLine->Level;
|
||||
} else {
|
||||
NextNonCommentLine = (*I)->First->isNot(tok::r_brace) ? (*I) : nullptr;
|
||||
}
|
||||
|
@ -234,14 +234,17 @@ UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
|
||||
CurrentLines(&Lines), Style(Style), Keywords(Keywords),
|
||||
CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
|
||||
Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
|
||||
IfNdefCondition(nullptr), FoundIncludeGuardStart(false),
|
||||
IncludeGuardRejected(false), FirstStartColumn(FirstStartColumn) {}
|
||||
IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None
|
||||
? IG_Rejected
|
||||
: IG_Inited),
|
||||
IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn) {}
|
||||
|
||||
void UnwrappedLineParser::reset() {
|
||||
PPBranchLevel = -1;
|
||||
IfNdefCondition = nullptr;
|
||||
FoundIncludeGuardStart = false;
|
||||
IncludeGuardRejected = false;
|
||||
IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None
|
||||
? IG_Rejected
|
||||
: IG_Inited;
|
||||
IncludeGuardToken = nullptr;
|
||||
Line.reset(new UnwrappedLine);
|
||||
CommentsBeforeNextToken.clear();
|
||||
FormatTok = nullptr;
|
||||
@ -264,6 +267,14 @@ void UnwrappedLineParser::parse() {
|
||||
|
||||
readToken();
|
||||
parseFile();
|
||||
|
||||
// If we found an include guard then all preprocessor directives (other than
|
||||
// the guard) are over-indented by one.
|
||||
if (IncludeGuard == IG_Found)
|
||||
for (auto &Line : Lines)
|
||||
if (Line.InPPDirective && Line.Level > 0)
|
||||
--Line.Level;
|
||||
|
||||
// Create line with eof token.
|
||||
pushToken(FormatTok);
|
||||
addUnwrappedLine();
|
||||
@ -712,26 +723,27 @@ void UnwrappedLineParser::parsePPIf(bool IfDef) {
|
||||
// If there's a #ifndef on the first line, and the only lines before it are
|
||||
// comments, it could be an include guard.
|
||||
bool MaybeIncludeGuard = IfNDef;
|
||||
if (!IncludeGuardRejected && !FoundIncludeGuardStart && MaybeIncludeGuard) {
|
||||
if (IncludeGuard == IG_Inited && MaybeIncludeGuard)
|
||||
for (auto &Line : Lines) {
|
||||
if (!Line.Tokens.front().Tok->is(tok::comment)) {
|
||||
MaybeIncludeGuard = false;
|
||||
IncludeGuardRejected = true;
|
||||
IncludeGuard = IG_Rejected;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
--PPBranchLevel;
|
||||
parsePPUnknown();
|
||||
++PPBranchLevel;
|
||||
if (!IncludeGuardRejected && !FoundIncludeGuardStart && MaybeIncludeGuard)
|
||||
IfNdefCondition = IfCondition;
|
||||
if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
|
||||
IncludeGuard = IG_IfNdefed;
|
||||
IncludeGuardToken = IfCondition;
|
||||
}
|
||||
}
|
||||
|
||||
void UnwrappedLineParser::parsePPElse() {
|
||||
// If a potential include guard has an #else, it's not an include guard.
|
||||
if (FoundIncludeGuardStart && PPBranchLevel == 0)
|
||||
FoundIncludeGuardStart = false;
|
||||
if (IncludeGuard == IG_Defined && PPBranchLevel == 0)
|
||||
IncludeGuard = IG_Rejected;
|
||||
conditionalCompilationAlternative();
|
||||
if (PPBranchLevel > -1)
|
||||
--PPBranchLevel;
|
||||
@ -745,34 +757,37 @@ void UnwrappedLineParser::parsePPEndIf() {
|
||||
conditionalCompilationEnd();
|
||||
parsePPUnknown();
|
||||
// If the #endif of a potential include guard is the last thing in the file,
|
||||
// then we count it as a real include guard and subtract one from every
|
||||
// preprocessor indent.
|
||||
// then we found an include guard.
|
||||
unsigned TokenPosition = Tokens->getPosition();
|
||||
FormatToken *PeekNext = AllTokens[TokenPosition];
|
||||
if (FoundIncludeGuardStart && PPBranchLevel == -1 && PeekNext->is(tok::eof) &&
|
||||
if (IncludeGuard == IG_Defined && PPBranchLevel == -1 &&
|
||||
PeekNext->is(tok::eof) &&
|
||||
Style.IndentPPDirectives != FormatStyle::PPDIS_None)
|
||||
for (auto &Line : Lines)
|
||||
if (Line.InPPDirective && Line.Level > 0)
|
||||
--Line.Level;
|
||||
IncludeGuard = IG_Found;
|
||||
}
|
||||
|
||||
void UnwrappedLineParser::parsePPDefine() {
|
||||
nextToken();
|
||||
|
||||
if (FormatTok->Tok.getKind() != tok::identifier) {
|
||||
IncludeGuard = IG_Rejected;
|
||||
IncludeGuardToken = nullptr;
|
||||
parsePPUnknown();
|
||||
return;
|
||||
}
|
||||
if (IfNdefCondition && IfNdefCondition->TokenText == FormatTok->TokenText) {
|
||||
FoundIncludeGuardStart = true;
|
||||
|
||||
if (IncludeGuard == IG_IfNdefed &&
|
||||
IncludeGuardToken->TokenText == FormatTok->TokenText) {
|
||||
IncludeGuard = IG_Defined;
|
||||
IncludeGuardToken = nullptr;
|
||||
for (auto &Line : Lines) {
|
||||
if (!Line.Tokens.front().Tok->isOneOf(tok::comment, tok::hash)) {
|
||||
FoundIncludeGuardStart = false;
|
||||
IncludeGuard = IG_Rejected;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
IfNdefCondition = nullptr;
|
||||
|
||||
nextToken();
|
||||
if (FormatTok->Tok.getKind() == tok::l_paren &&
|
||||
FormatTok->WhitespaceRange.getBegin() ==
|
||||
@ -799,7 +814,6 @@ void UnwrappedLineParser::parsePPUnknown() {
|
||||
if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash)
|
||||
Line->Level += PPBranchLevel + 1;
|
||||
addUnwrappedLine();
|
||||
IfNdefCondition = nullptr;
|
||||
}
|
||||
|
||||
// Here we blacklist certain tokens that are not usually the first token in an
|
||||
|
@ -248,10 +248,23 @@ class UnwrappedLineParser {
|
||||
// sequence.
|
||||
std::stack<int> PPChainBranchIndex;
|
||||
|
||||
// Contains the #ifndef condition for a potential include guard.
|
||||
FormatToken *IfNdefCondition;
|
||||
bool FoundIncludeGuardStart;
|
||||
bool IncludeGuardRejected;
|
||||
// Include guard search state. Used to fixup preprocessor indent levels
|
||||
// so that include guards do not participate in indentation.
|
||||
enum IncludeGuardState {
|
||||
IG_Inited, // Search started, looking for #ifndef.
|
||||
IG_IfNdefed, // #ifndef found, IncludeGuardToken points to condition.
|
||||
IG_Defined, // Matching #define found, checking other requirements.
|
||||
IG_Found, // All requirements met, need to fix indents.
|
||||
IG_Rejected, // Search failed or never started.
|
||||
};
|
||||
|
||||
// Current state of include guard search.
|
||||
IncludeGuardState IncludeGuard;
|
||||
|
||||
// Points to the #ifndef condition for a potential include guard. Null unless
|
||||
// IncludeGuardState == IG_IfNdefed.
|
||||
FormatToken *IncludeGuardToken;
|
||||
|
||||
// Contains the first start column where the source begins. This is zero for
|
||||
// normal source code and may be nonzero when formatting a code fragment that
|
||||
// does not start at the beginning of the file.
|
||||
|
@ -1854,13 +1854,15 @@ _mm512_maskz_set1_epi8 (__mmask64 __M, char __A)
|
||||
static __inline__ __mmask64 __DEFAULT_FN_ATTRS
|
||||
_mm512_kunpackd (__mmask64 __A, __mmask64 __B)
|
||||
{
|
||||
return (__mmask64) (( __A & 0xFFFFFFFF) | ( __B << 32));
|
||||
return (__mmask64) __builtin_ia32_kunpckdi ((__mmask64) __A,
|
||||
(__mmask64) __B);
|
||||
}
|
||||
|
||||
static __inline__ __mmask32 __DEFAULT_FN_ATTRS
|
||||
_mm512_kunpackw (__mmask32 __A, __mmask32 __B)
|
||||
{
|
||||
return (__mmask32) (( __A & 0xFFFF) | ( __B << 16));
|
||||
return (__mmask32) __builtin_ia32_kunpcksi ((__mmask32) __A,
|
||||
(__mmask32) __B);
|
||||
}
|
||||
|
||||
static __inline__ __m512i __DEFAULT_FN_ATTRS
|
||||
|
@ -8787,7 +8787,7 @@ _mm512_kortestz (__mmask16 __A, __mmask16 __B)
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
_mm512_kunpackb (__mmask16 __A, __mmask16 __B)
|
||||
{
|
||||
return (__mmask16) (( __A & 0xFF) | ( __B << 8));
|
||||
return (__mmask16) __builtin_ia32_kunpckhi ((__mmask16) __A, (__mmask16) __B);
|
||||
}
|
||||
|
||||
static __inline__ __mmask16 __DEFAULT_FN_ATTRS
|
||||
|
@ -738,15 +738,17 @@ void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){
|
||||
s++;
|
||||
radix = 10;
|
||||
saw_exponent = true;
|
||||
if (*s == '+' || *s == '-') s++; // sign
|
||||
if (s != ThisTokEnd && (*s == '+' || *s == '-')) s++; // sign
|
||||
const char *first_non_digit = SkipDigits(s);
|
||||
if (containsDigits(s, first_non_digit)) {
|
||||
checkSeparator(TokLoc, s, CSK_BeforeDigits);
|
||||
s = first_non_digit;
|
||||
} else {
|
||||
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
|
||||
diag::err_exponent_has_no_digits);
|
||||
hadError = true;
|
||||
if (!hadError) {
|
||||
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
|
||||
diag::err_exponent_has_no_digits);
|
||||
hadError = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -787,10 +789,12 @@ void NumericLiteralParser::checkSeparator(SourceLocation TokLoc,
|
||||
} else if (Pos == ThisTokEnd)
|
||||
return;
|
||||
|
||||
if (isDigitSeparator(*Pos))
|
||||
if (isDigitSeparator(*Pos)) {
|
||||
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Pos - ThisTokBegin),
|
||||
diag::err_digit_separator_not_between_digits)
|
||||
<< IsAfterDigits;
|
||||
hadError = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// ParseNumberStartingWithZero - This method is called when the first character
|
||||
@ -840,12 +844,14 @@ void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
|
||||
const char *Exponent = s;
|
||||
s++;
|
||||
saw_exponent = true;
|
||||
if (*s == '+' || *s == '-') s++; // sign
|
||||
if (s != ThisTokEnd && (*s == '+' || *s == '-')) s++; // sign
|
||||
const char *first_non_digit = SkipDigits(s);
|
||||
if (!containsDigits(s, first_non_digit)) {
|
||||
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
|
||||
diag::err_exponent_has_no_digits);
|
||||
hadError = true;
|
||||
if (!hadError) {
|
||||
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
|
||||
diag::err_exponent_has_no_digits);
|
||||
hadError = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
checkSeparator(TokLoc, s, CSK_BeforeDigits);
|
||||
|
@ -8972,6 +8972,16 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
|
||||
LHS = LHS->IgnoreParenImpCasts();
|
||||
RHS = RHS->IgnoreParenImpCasts();
|
||||
|
||||
if (!S.getLangOpts().CPlusPlus) {
|
||||
// Avoid warning about comparison of integers with different signs when
|
||||
// RHS/LHS has a `typeof(E)` type whose sign is different from the sign of
|
||||
// the type of `E`.
|
||||
if (const auto *TET = dyn_cast<TypeOfExprType>(LHS->getType()))
|
||||
LHS = TET->getUnderlyingExpr()->IgnoreParenImpCasts();
|
||||
if (const auto *TET = dyn_cast<TypeOfExprType>(RHS->getType()))
|
||||
RHS = TET->getUnderlyingExpr()->IgnoreParenImpCasts();
|
||||
}
|
||||
|
||||
// Check to see if one of the (unmodified) operands is of different
|
||||
// signedness.
|
||||
Expr *signedOperand, *unsignedOperand;
|
||||
|
@ -12507,10 +12507,20 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
|
||||
/// call, forming a call to an implicitly defined function (per C99 6.5.1p2).
|
||||
NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
|
||||
IdentifierInfo &II, Scope *S) {
|
||||
// Find the scope in which the identifier is injected and the corresponding
|
||||
// DeclContext.
|
||||
// FIXME: C89 does not say what happens if there is no enclosing block scope.
|
||||
// In that case, we inject the declaration into the translation unit scope
|
||||
// instead.
|
||||
Scope *BlockScope = S;
|
||||
while (!BlockScope->isCompoundStmtScope() && BlockScope->getParent())
|
||||
BlockScope = BlockScope->getParent();
|
||||
|
||||
Scope *ContextScope = BlockScope;
|
||||
while (!ContextScope->getEntity())
|
||||
ContextScope = ContextScope->getParent();
|
||||
ContextRAII SavedContext(*this, ContextScope->getEntity());
|
||||
|
||||
// Before we produce a declaration for an implicitly defined
|
||||
// function, see whether there was a locally-scoped declaration of
|
||||
// this name as a function or variable. If so, use that
|
||||
|
@ -352,6 +352,7 @@ class InitListChecker {
|
||||
bool FillWithNoInit = false);
|
||||
void FillInEmptyInitializations(const InitializedEntity &Entity,
|
||||
InitListExpr *ILE, bool &RequiresSecondPass,
|
||||
InitListExpr *OuterILE, unsigned OuterIndex,
|
||||
bool FillWithNoInit = false);
|
||||
bool CheckFlexibleArrayInit(const InitializedEntity &Entity,
|
||||
Expr *InitExpr, FieldDecl *Field,
|
||||
@ -517,12 +518,13 @@ void InitListChecker::FillInEmptyInitForBase(
|
||||
ILE->setInit(Init, BaseInit.getAs<Expr>());
|
||||
} else if (InitListExpr *InnerILE =
|
||||
dyn_cast<InitListExpr>(ILE->getInit(Init))) {
|
||||
FillInEmptyInitializations(BaseEntity, InnerILE,
|
||||
RequiresSecondPass, FillWithNoInit);
|
||||
FillInEmptyInitializations(BaseEntity, InnerILE, RequiresSecondPass,
|
||||
ILE, Init, FillWithNoInit);
|
||||
} else if (DesignatedInitUpdateExpr *InnerDIUE =
|
||||
dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init))) {
|
||||
FillInEmptyInitializations(BaseEntity, InnerDIUE->getUpdater(),
|
||||
RequiresSecondPass, /*FillWithNoInit =*/true);
|
||||
RequiresSecondPass, ILE, Init,
|
||||
/*FillWithNoInit =*/true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,24 +607,43 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
|
||||
} else if (InitListExpr *InnerILE
|
||||
= dyn_cast<InitListExpr>(ILE->getInit(Init)))
|
||||
FillInEmptyInitializations(MemberEntity, InnerILE,
|
||||
RequiresSecondPass, FillWithNoInit);
|
||||
RequiresSecondPass, ILE, Init, FillWithNoInit);
|
||||
else if (DesignatedInitUpdateExpr *InnerDIUE
|
||||
= dyn_cast<DesignatedInitUpdateExpr>(ILE->getInit(Init)))
|
||||
FillInEmptyInitializations(MemberEntity, InnerDIUE->getUpdater(),
|
||||
RequiresSecondPass, /*FillWithNoInit =*/ true);
|
||||
RequiresSecondPass, ILE, Init,
|
||||
/*FillWithNoInit =*/true);
|
||||
}
|
||||
|
||||
/// Recursively replaces NULL values within the given initializer list
|
||||
/// with expressions that perform value-initialization of the
|
||||
/// appropriate type.
|
||||
/// appropriate type, and finish off the InitListExpr formation.
|
||||
void
|
||||
InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
|
||||
InitListExpr *ILE,
|
||||
bool &RequiresSecondPass,
|
||||
InitListExpr *OuterILE,
|
||||
unsigned OuterIndex,
|
||||
bool FillWithNoInit) {
|
||||
assert((ILE->getType() != SemaRef.Context.VoidTy) &&
|
||||
"Should not have void type");
|
||||
|
||||
// If this is a nested initializer list, we might have changed its contents
|
||||
// (and therefore some of its properties, such as instantiation-dependence)
|
||||
// while filling it in. Inform the outer initializer list so that its state
|
||||
// can be updated to match.
|
||||
// FIXME: We should fully build the inner initializers before constructing
|
||||
// the outer InitListExpr instead of mutating AST nodes after they have
|
||||
// been used as subexpressions of other nodes.
|
||||
struct UpdateOuterILEWithUpdatedInit {
|
||||
InitListExpr *Outer;
|
||||
unsigned OuterIndex;
|
||||
~UpdateOuterILEWithUpdatedInit() {
|
||||
if (Outer)
|
||||
Outer->setInit(OuterIndex, Outer->getInit(OuterIndex));
|
||||
}
|
||||
} UpdateOuterRAII = {OuterILE, OuterIndex};
|
||||
|
||||
// A transparent ILE is not performing aggregate initialization and should
|
||||
// not be filled in.
|
||||
if (ILE->isTransparent())
|
||||
@ -769,11 +790,12 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity,
|
||||
} else if (InitListExpr *InnerILE
|
||||
= dyn_cast_or_null<InitListExpr>(InitExpr))
|
||||
FillInEmptyInitializations(ElementEntity, InnerILE, RequiresSecondPass,
|
||||
FillWithNoInit);
|
||||
ILE, Init, FillWithNoInit);
|
||||
else if (DesignatedInitUpdateExpr *InnerDIUE
|
||||
= dyn_cast_or_null<DesignatedInitUpdateExpr>(InitExpr))
|
||||
FillInEmptyInitializations(ElementEntity, InnerDIUE->getUpdater(),
|
||||
RequiresSecondPass, /*FillWithNoInit =*/ true);
|
||||
RequiresSecondPass, ILE, Init,
|
||||
/*FillWithNoInit =*/true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,10 +817,11 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity,
|
||||
|
||||
if (!hadError && !VerifyOnly) {
|
||||
bool RequiresSecondPass = false;
|
||||
FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass);
|
||||
FillInEmptyInitializations(Entity, FullyStructuredList, RequiresSecondPass,
|
||||
/*OuterILE=*/nullptr, /*OuterIndex=*/0);
|
||||
if (RequiresSecondPass && !hadError)
|
||||
FillInEmptyInitializations(Entity, FullyStructuredList,
|
||||
RequiresSecondPass);
|
||||
RequiresSecondPass, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1162,10 +1185,12 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
|
||||
if (!hadError && !VerifyOnly) {
|
||||
bool RequiresSecondPass = false;
|
||||
FillInEmptyInitializations(Entity, InnerStructuredList,
|
||||
RequiresSecondPass);
|
||||
RequiresSecondPass, StructuredList,
|
||||
StructuredIndex);
|
||||
if (RequiresSecondPass && !hadError)
|
||||
FillInEmptyInitializations(Entity, InnerStructuredList,
|
||||
RequiresSecondPass);
|
||||
RequiresSecondPass, StructuredList,
|
||||
StructuredIndex);
|
||||
}
|
||||
++StructuredIndex;
|
||||
++Index;
|
||||
|
@ -1626,26 +1626,16 @@ __m512i test_mm512_maskz_set1_epi8(__mmask64 __M, char __A) {
|
||||
return _mm512_maskz_set1_epi8(__M, __A);
|
||||
}
|
||||
|
||||
__mmask64 test_mm512_kunpackd(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
|
||||
__mmask64 test_mm512_kunpackd(__mmask64 __A, __mmask64 __B) {
|
||||
// CHECK-LABEL: @test_mm512_kunpackd
|
||||
// CHECK: bitcast <64 x i1> %{{.*}} to i64
|
||||
// CHECK: bitcast <64 x i1> %{{.*}} to i64
|
||||
// CHECK: and i64 %{{.*}}, 4294967295
|
||||
// CHECK: shl i64 %{{.*}}, 32
|
||||
// CHECK: or i64 %{{.*}}, %{{.*}}
|
||||
// CHECK: bitcast i64 %{{.*}} to <64 x i1>
|
||||
return _mm512_mask_cmpneq_epu8_mask(_mm512_kunpackd(_mm512_cmpneq_epu8_mask(__B, __A),_mm512_cmpneq_epu8_mask(__C, __D)), __E, __F);
|
||||
// CHECK: @llvm.x86.avx512.kunpck.dq
|
||||
return _mm512_kunpackd(__A, __B);
|
||||
}
|
||||
|
||||
__mmask32 test_mm512_kunpackw(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
|
||||
__mmask32 test_mm512_kunpackw(__mmask32 __A, __mmask32 __B) {
|
||||
// CHECK-LABEL: @test_mm512_kunpackw
|
||||
// CHECK: bitcast <32 x i1> %{{.*}} to i32
|
||||
// CHECK: bitcast <32 x i1> %{{.*}} to i32
|
||||
// CHECK: and i32 %{{.*}}, 65535
|
||||
// CHECK: shl i32 %{{.*}}, 16
|
||||
// CHECK: or i32 %{{.*}}, %{{.*}}
|
||||
// CHECK: bitcast i32 %{{.*}} to <32 x i1>
|
||||
return _mm512_mask_cmpneq_epu16_mask(_mm512_kunpackw(_mm512_cmpneq_epu16_mask(__B, __A),_mm512_cmpneq_epu16_mask(__C, __D)), __E, __F);
|
||||
// CHECK: @llvm.x86.avx512.kunpck.wd
|
||||
return _mm512_kunpackw(__A, __B);
|
||||
}
|
||||
|
||||
__m512i test_mm512_mask_loadu_epi16(__m512i __W, __mmask32 __U, void const *__P) {
|
||||
|
@ -6259,17 +6259,10 @@ int test_mm512_kortestz(__mmask16 __A, __mmask16 __B) {
|
||||
return _mm512_kortestz(__A, __B);
|
||||
}
|
||||
|
||||
__mmask16 test_mm512_kunpackb(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
|
||||
__mmask16 test_mm512_kunpackb(__mmask16 __A, __mmask16 __B) {
|
||||
// CHECK-LABEL: @test_mm512_kunpackb
|
||||
// CHECK: bitcast <16 x i1> %{{.*}} to i16
|
||||
// CHECK: bitcast <16 x i1> %{{.*}} to i16
|
||||
// CHECK: and i32 %{{.*}}, 255
|
||||
// CHECK: shl i32 %{{.*}}, 8
|
||||
// CHECK: or i32 %{{.*}}, %{{.*}}
|
||||
// CHECK: bitcast i16 %{{.*}} to <16 x i1>
|
||||
return _mm512_mask_cmpneq_epu32_mask(_mm512_kunpackb(_mm512_cmpneq_epu32_mask(__A, __B),
|
||||
_mm512_cmpneq_epu32_mask(__C, __D)),
|
||||
__E, __F);
|
||||
// CHECK: @llvm.x86.avx512.kunpck.bw
|
||||
return _mm512_kunpackb(__A, __B);
|
||||
}
|
||||
|
||||
__mmask16 test_mm512_kxnor(__m512i __A, __m512i __B, __m512i __C, __m512i __D, __m512i __E, __m512i __F) {
|
||||
|
@ -146,3 +146,16 @@ void __attribute__((sysv_abi)) f6(__builtin_ms_va_list ap) {
|
||||
// WIN64: %[[AP_VAL:.*]] = load i8*, i8** %[[AP]]
|
||||
// WIN64-NEXT: store i8* %[[AP_VAL]], i8** %[[AP2:.*]]
|
||||
}
|
||||
|
||||
// This test checks if structs are passed according to Win64 calling convention
|
||||
// when it's enforced by __attribute((ms_abi)).
|
||||
struct i128 {
|
||||
unsigned long long a;
|
||||
unsigned long long b;
|
||||
};
|
||||
|
||||
__attribute__((ms_abi)) struct i128 f7(struct i128 a) {
|
||||
// WIN64: define void @f7(%struct.i128* noalias sret %agg.result, %struct.i128* %a)
|
||||
// FREEBSD: define win64cc void @f7(%struct.i128* noalias sret %agg.result, %struct.i128* %a)
|
||||
return a;
|
||||
}
|
||||
|
20
test/CodeGenCXX/dllimport-missing-key.cpp
Normal file
20
test/CodeGenCXX/dllimport-missing-key.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
// RUN: %clang_cc1 -triple i686-windows-gnu -emit-llvm -std=c++1y -O0 -o - %s -w | FileCheck --check-prefix=GNU %s
|
||||
|
||||
class __declspec(dllimport) QObjectData {
|
||||
public:
|
||||
virtual ~QObjectData() = 0;
|
||||
void *ptr;
|
||||
|
||||
int method() const;
|
||||
};
|
||||
|
||||
class LocalClass : public QObjectData {
|
||||
};
|
||||
|
||||
void call() {
|
||||
(new LocalClass())->method();
|
||||
}
|
||||
|
||||
// GNU-DAG: @_ZTV11QObjectData = available_externally dllimport
|
||||
// GNU-DAG: @_ZTS11QObjectData = linkonce_odr
|
||||
// GNU-DAG: @_ZTI11QObjectData = linkonce_odr
|
@ -12,7 +12,7 @@ struct __declspec(dllimport) S {
|
||||
// MSVC-DAG: @"\01??_R3S@@8" = linkonce_odr
|
||||
|
||||
// GNU-DAG: @_ZTV1S = available_externally dllimport
|
||||
// GNU-DAG: @_ZTI1S = external dllimport
|
||||
// GNU-DAG: @_ZTI1S = linkonce_odr
|
||||
|
||||
struct U : S {
|
||||
} u;
|
||||
|
11
test/CodeGenCXX/microsoft-abi-emit-dependent.cpp
Normal file
11
test/CodeGenCXX/microsoft-abi-emit-dependent.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
// RUN: %clang_cc1 -emit-llvm-only -fmodules -triple x86_64-windows %s
|
||||
// PR36181
|
||||
#pragma clang module build foo
|
||||
module foo {}
|
||||
#pragma clang module contents
|
||||
template <typename T> struct A {
|
||||
friend void f(A<T>) {}
|
||||
};
|
||||
#pragma clang module endbuild
|
||||
#pragma clang module import foo
|
||||
void g() { f(A<int>()); }
|
28
test/CodeGenCXX/msabi-swiftcall-cc.cpp
Normal file
28
test/CodeGenCXX/msabi-swiftcall-cc.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
// RUN: %clang_cc1 -triple i686-unknown-windows-msvc -fdeclspec -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
void __attribute__((__swiftcall__)) f() {}
|
||||
// CHECK-DAG: @"\01?f@@YSXXZ"
|
||||
|
||||
void (__attribute__((__swiftcall__)) *p)();
|
||||
// CHECK-DAG: @"\01?p@@3P6SXXZA"
|
||||
|
||||
namespace {
|
||||
void __attribute__((__swiftcall__)) __attribute__((__used__)) f() { }
|
||||
// CHECK-DAG: "\01?f@?A@@YSXXZ"
|
||||
}
|
||||
|
||||
namespace n {
|
||||
void __attribute__((__swiftcall__)) f() {}
|
||||
// CHECK-DAG: "\01?f@n@@YSXXZ"
|
||||
}
|
||||
|
||||
struct __declspec(dllexport) S {
|
||||
S(const S &) = delete;
|
||||
S & operator=(const S &) = delete;
|
||||
void __attribute__((__swiftcall__)) m() { }
|
||||
// CHECK-DAG: "\01?m@S@@QASXXZ"
|
||||
};
|
||||
|
||||
void f(void (__attribute__((__swiftcall__))())) {}
|
||||
// CHECK-DAG: "\01?f@@YAXP6SXXZ@Z"
|
||||
|
@ -51,6 +51,8 @@ namespace floating {
|
||||
float u = 0x.'p1f; // expected-error {{hexadecimal floating literal requires a significand}}
|
||||
float v = 0e'f; // expected-error {{exponent has no digits}}
|
||||
float w = 0x0p'f; // expected-error {{exponent has no digits}}
|
||||
float x = 0'e+1; // expected-error {{digit separator cannot appear at end of digit sequence}}
|
||||
float y = 0x0'p+1; // expected-error {{digit separator cannot appear at end of digit sequence}}
|
||||
}
|
||||
|
||||
#line 123'456
|
||||
|
@ -82,3 +82,7 @@ typedef __typeof__(+(t5.n--)) Unsigned; // also act like compound-assignment.
|
||||
struct Test6 {
|
||||
: 0.0; // expected-error{{type name requires a specifier or qualifier}}
|
||||
};
|
||||
|
||||
struct PR36157 {
|
||||
int n : 1 ? 1 : implicitly_declare_function(); // expected-warning {{invalid in C99}}
|
||||
};
|
||||
|
@ -391,3 +391,16 @@ typedef char two_chars[2];
|
||||
void test12(unsigned a) {
|
||||
if (0 && -1 > a) { }
|
||||
}
|
||||
|
||||
// PR36008
|
||||
|
||||
enum PR36008EnumTest {
|
||||
kPR36008Value = 0,
|
||||
};
|
||||
|
||||
void pr36008(enum PR36008EnumTest lhs) {
|
||||
__typeof__(lhs) x = lhs;
|
||||
__typeof__(kPR36008Value) y = (kPR36008Value);
|
||||
if (x == y) x = y; // no warning
|
||||
if (y == x) y = x; // no warning
|
||||
}
|
||||
|
9
test/Sema/cxx-as-c.c
Normal file
9
test/Sema/cxx-as-c.c
Normal file
@ -0,0 +1,9 @@
|
||||
// RUN: %clang_cc1 %s -verify
|
||||
|
||||
// PR36157
|
||||
struct Foo {
|
||||
Foo(int n) : n_(n) {} // expected-error 1+{{}} expected-warning 1+{{}}
|
||||
private:
|
||||
int n;
|
||||
};
|
||||
int main() { Foo f; } // expected-error 1+{{}}
|
@ -29,3 +29,11 @@ template <class T> struct B {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// This test checks for a crash that resulted from us miscomputing the
|
||||
// dependence of a nested initializer list.
|
||||
template<int> struct X {
|
||||
static constexpr int n = 4;
|
||||
static constexpr int a[1][1] = {n};
|
||||
};
|
||||
|
||||
|
@ -2524,6 +2524,7 @@ static_assert(!has_unique_object_representations<const int &>::value, "No refere
|
||||
static_assert(!has_unique_object_representations<volatile int &>::value, "No references!");
|
||||
static_assert(!has_unique_object_representations<const volatile int &>::value, "No references!");
|
||||
static_assert(!has_unique_object_representations<Empty>::value, "No empty types!");
|
||||
static_assert(!has_unique_object_representations<EmptyUnion>::value, "No empty types!");
|
||||
|
||||
class Compressed : Empty {
|
||||
int x;
|
||||
|
@ -142,3 +142,17 @@ namespace ReturnStmtIsInitialization {
|
||||
template<typename T> X f() { return {}; }
|
||||
auto &&x = f<void>();
|
||||
}
|
||||
|
||||
namespace InitListUpdate {
|
||||
struct A { int n; };
|
||||
using AA = A[1];
|
||||
|
||||
// Check that an init list update doesn't "lose" the pack-ness of an expression.
|
||||
template <int... N> void f() {
|
||||
g(AA{0, [0].n = N} ...); // expected-warning 3{{overrides prior init}} expected-note 3{{previous init}}
|
||||
g(AA{N, [0].n = 0} ...); // expected-warning 3{{overrides prior init}} expected-note 3{{previous init}}
|
||||
};
|
||||
|
||||
void g(AA, AA);
|
||||
void h() { f<1, 2>(); } // expected-note {{instantiation of}}
|
||||
}
|
||||
|
@ -2532,6 +2532,20 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) {
|
||||
"#elif FOO\n"
|
||||
"#endif",
|
||||
Style);
|
||||
// Non-identifier #define after potential include guard.
|
||||
verifyFormat("#ifndef FOO\n"
|
||||
"# define 1\n"
|
||||
"#endif\n",
|
||||
Style);
|
||||
// #if closes past last non-preprocessor line.
|
||||
verifyFormat("#ifndef FOO\n"
|
||||
"#define FOO\n"
|
||||
"#if 1\n"
|
||||
"int i;\n"
|
||||
"# define A 0\n"
|
||||
"#endif\n"
|
||||
"#endif\n",
|
||||
Style);
|
||||
// FIXME: This doesn't handle the case where there's code between the
|
||||
// #ifndef and #define but all other conditions hold. This is because when
|
||||
// the #define line is parsed, UnwrappedLineParser::Lines doesn't hold the
|
||||
@ -2580,21 +2594,85 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) {
|
||||
"code();\n"
|
||||
"#endif",
|
||||
Style));
|
||||
// FIXME: The comment indent corrector in TokenAnnotator gets thrown off by
|
||||
// preprocessor indentation.
|
||||
EXPECT_EQ("#if 1\n"
|
||||
" // comment\n"
|
||||
"# define A 0\n"
|
||||
"// comment\n"
|
||||
"# define B 0\n"
|
||||
"#endif",
|
||||
format("#if 1\n"
|
||||
"// comment\n"
|
||||
"# define A 0\n"
|
||||
" // comment\n"
|
||||
"# define B 0\n"
|
||||
"#endif",
|
||||
Style));
|
||||
// Keep comments aligned with #, otherwise indent comments normally. These
|
||||
// tests cannot use verifyFormat because messUp manipulates leading
|
||||
// whitespace.
|
||||
{
|
||||
const char *Expected = ""
|
||||
"void f() {\n"
|
||||
"#if 1\n"
|
||||
"// Preprocessor aligned.\n"
|
||||
"# define A 0\n"
|
||||
" // Code. Separated by blank line.\n"
|
||||
"\n"
|
||||
"# define B 0\n"
|
||||
" // Code. Not aligned with #\n"
|
||||
"# define C 0\n"
|
||||
"#endif";
|
||||
const char *ToFormat = ""
|
||||
"void f() {\n"
|
||||
"#if 1\n"
|
||||
"// Preprocessor aligned.\n"
|
||||
"# define A 0\n"
|
||||
"// Code. Separated by blank line.\n"
|
||||
"\n"
|
||||
"# define B 0\n"
|
||||
" // Code. Not aligned with #\n"
|
||||
"# define C 0\n"
|
||||
"#endif";
|
||||
EXPECT_EQ(Expected, format(ToFormat, Style));
|
||||
EXPECT_EQ(Expected, format(Expected, Style));
|
||||
}
|
||||
// Keep block quotes aligned.
|
||||
{
|
||||
const char *Expected = ""
|
||||
"void f() {\n"
|
||||
"#if 1\n"
|
||||
"/* Preprocessor aligned. */\n"
|
||||
"# define A 0\n"
|
||||
" /* Code. Separated by blank line. */\n"
|
||||
"\n"
|
||||
"# define B 0\n"
|
||||
" /* Code. Not aligned with # */\n"
|
||||
"# define C 0\n"
|
||||
"#endif";
|
||||
const char *ToFormat = ""
|
||||
"void f() {\n"
|
||||
"#if 1\n"
|
||||
"/* Preprocessor aligned. */\n"
|
||||
"# define A 0\n"
|
||||
"/* Code. Separated by blank line. */\n"
|
||||
"\n"
|
||||
"# define B 0\n"
|
||||
" /* Code. Not aligned with # */\n"
|
||||
"# define C 0\n"
|
||||
"#endif";
|
||||
EXPECT_EQ(Expected, format(ToFormat, Style));
|
||||
EXPECT_EQ(Expected, format(Expected, Style));
|
||||
}
|
||||
// Keep comments aligned with un-indented directives.
|
||||
{
|
||||
const char *Expected = ""
|
||||
"void f() {\n"
|
||||
"// Preprocessor aligned.\n"
|
||||
"#define A 0\n"
|
||||
" // Code. Separated by blank line.\n"
|
||||
"\n"
|
||||
"#define B 0\n"
|
||||
" // Code. Not aligned with #\n"
|
||||
"#define C 0\n";
|
||||
const char *ToFormat = ""
|
||||
"void f() {\n"
|
||||
"// Preprocessor aligned.\n"
|
||||
"#define A 0\n"
|
||||
"// Code. Separated by blank line.\n"
|
||||
"\n"
|
||||
"#define B 0\n"
|
||||
" // Code. Not aligned with #\n"
|
||||
"#define C 0\n";
|
||||
EXPECT_EQ(Expected, format(ToFormat, Style));
|
||||
EXPECT_EQ(Expected, format(Expected, Style));
|
||||
}
|
||||
// Test with tabs.
|
||||
Style.UseTab = FormatStyle::UT_Always;
|
||||
Style.IndentWidth = 8;
|
||||
|
Loading…
Reference in New Issue
Block a user