Skip to content

Commit

Permalink
Add type information to integral template argument if required.
Browse files Browse the repository at this point in the history
Non-comprehensive list of cases:
 * Dumping template arguments;
 * Corresponding parameter contains a deduced type;
 * Template arguments are for a DeclRefExpr that hadMultipleCandidates()

Type information is added in the form of prefixes (u8, u, U, L),
suffixes (U, L, UL, LL, ULL) or explicit casts to printed integral template
argument, if MSVC codeview mode is disabled.

Differential revision: https://reviews.llvm.org/D77598
  • Loading branch information
reikdas authored and vgvassilev committed May 12, 2021
1 parent d8c227b commit 99d63cc
Show file tree
Hide file tree
Showing 38 changed files with 434 additions and 162 deletions.
3 changes: 2 additions & 1 deletion clang-tools-extra/clangd/Hover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ fetchTemplateParameters(const TemplateParameterList *Params,
if (TTPD->hasDefaultArgument()) {
P.Default.emplace();
llvm::raw_string_ostream Out(*P.Default);
TTPD->getDefaultArgument().getArgument().print(PP, Out);
TTPD->getDefaultArgument().getArgument().print(PP, Out,
/*IncludeType*/ false);
}
}
TempParameters.push_back(std::move(P));
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ class TemplateParameterList final
bool OmitTemplateKW = false) const;
void print(raw_ostream &Out, const ASTContext &Context,
const PrintingPolicy &Policy, bool OmitTemplateKW = false) const;

static bool shouldIncludeTypeForArgument(const TemplateParameterList *TPL,
unsigned Idx);
};

/// Stores a list of template parameters and the associated
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,8 @@ class CharacterLiteral : public Expr {
return T->getStmtClass() == CharacterLiteralClass;
}

static void print(unsigned val, CharacterKind Kind, raw_ostream &OS);

// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/StmtDataCollectors.td
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class CallExpr {
// Print all template arguments into ArgString
llvm::raw_string_ostream OS(ArgString);
for (unsigned i = 0; i < Args->size(); ++i) {
Args->get(i).print(Context.getLangOpts(), OS);
Args->get(i).print(Context.getLangOpts(), OS, /*IncludeType*/ true);
// Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
OS << '\n';
}
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/AST/TemplateBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,8 @@ class TemplateArgument {
TemplateArgument getPackExpansionPattern() const;

/// Print this template argument to the given output stream.
void print(const PrintingPolicy &Policy, raw_ostream &Out) const;
void print(const PrintingPolicy &Policy, raw_ostream &Out,
bool IncludeType) const;

/// Debugging aid that dumps the template argument.
void dump(raw_ostream &Out) const;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ASTTypeTraits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) {
void DynTypedNode::print(llvm::raw_ostream &OS,
const PrintingPolicy &PP) const {
if (const TemplateArgument *TA = get<TemplateArgument>())
TA->print(PP, OS);
TA->print(PP, OS, /*IncludeType*/ true);
else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
TAL->getArgument().print(PP, OS);
TAL->getArgument().print(PP, OS, /*IncludeType*/ true);
else if (const TemplateName *TN = get<TemplateName>())
TN->print(OS, PP);
else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
Expand Down
43 changes: 34 additions & 9 deletions clang/lib/AST/DeclPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,12 @@ namespace {

void printTemplateParameters(const TemplateParameterList *Params,
bool OmitTemplateKW = false);
void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args);
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args);
void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args,
const TemplateParameterList *Params,
bool TemplOverloaded);
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
const TemplateParameterList *Params,
bool TemplOverloaded);
void prettyPrintAttributes(Decl *D);
void prettyPrintPragmas(Decl *D);
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
Expand Down Expand Up @@ -644,11 +648,16 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
llvm::raw_string_ostream POut(Proto);
DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten();
const TemplateParameterList *TPL = D->getTemplateSpecializationInfo()
->getTemplate()
->getTemplateParameters();
if (TArgAsWritten && !Policy.PrintCanonicalTypes)
TArgPrinter.printTemplateArguments(TArgAsWritten->arguments());
TArgPrinter.printTemplateArguments(TArgAsWritten->arguments(), TPL,
/*TemplOverloaded*/ true);
else if (const TemplateArgumentList *TArgs =
D->getTemplateSpecializationArgs())
TArgPrinter.printTemplateArguments(TArgs->asArray());
TArgPrinter.printTemplateArguments(TArgs->asArray(), TPL,
/*TemplOverloaded*/ true);
}

QualType Ty = D->getType();
Expand Down Expand Up @@ -988,7 +997,9 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
if (const auto *TST =
dyn_cast<TemplateSpecializationType>(TSI->getType()))
Args = TST->template_arguments();
printTemplateArguments(Args);
printTemplateArguments(
Args, S->getSpecializedTemplate()->getTemplateParameters(),
/*TemplOverloaded*/ false);
}
}

Expand Down Expand Up @@ -1080,22 +1091,36 @@ void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params,
Out << ' ';
}

void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args) {
void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args,
const TemplateParameterList *Params,
bool TemplOverloaded) {
Out << "<";
for (size_t I = 0, E = Args.size(); I < E; ++I) {
if (I)
Out << ", ";
Args[I].print(Policy, Out);
if (TemplOverloaded || !Params)
Args[I].print(Policy, Out, /*IncludeType*/ true);
else
Args[I].print(
Policy, Out,
TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
}
Out << ">";
}

void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args) {
void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
const TemplateParameterList *Params,
bool TemplOverloaded) {
Out << "<";
for (size_t I = 0, E = Args.size(); I < E; ++I) {
if (I)
Out << ", ";
Args[I].getArgument().print(Policy, Out);
if (TemplOverloaded)
Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true);
else
Args[I].getArgument().print(
Policy, Out,
TemplateParameterList::shouldIncludeTypeForArgument(Params, I));
}
Out << ">";
}
Expand Down
15 changes: 14 additions & 1 deletion clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,18 @@ bool TemplateParameterList::hasAssociatedConstraints() const {
return HasRequiresClause || HasConstrainedParameters;
}

bool TemplateParameterList::shouldIncludeTypeForArgument(
const TemplateParameterList *TPL, unsigned Idx) {
if (!TPL || Idx >= TPL->size())
return true;
const NamedDecl *TemplParam = TPL->getParam(Idx);
if (const auto *ParamValueDecl =
dyn_cast<NonTypeTemplateParmDecl>(TemplParam))
if (ParamValueDecl->getType()->getContainedDeducedType())
return true;
return false;
}

namespace clang {

void *allocateDefaultArgStorageChain(const ASTContext &C) {
Expand Down Expand Up @@ -1420,8 +1432,9 @@ void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const {
ConceptName.printName(OS, Policy);
if (hasExplicitTemplateArgs()) {
OS << "<";
// FIXME: Find corresponding parameter for argument
for (auto &ArgLoc : ArgsAsWritten->arguments())
ArgLoc.getArgument().print(Policy, OS);
ArgLoc.getArgument().print(Policy, OS, /*IncludeType*/ false);
OS << ">";
}
}
Expand Down
77 changes: 75 additions & 2 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "clang/Lex/Lexer.h"
#include "clang/Lex/LiteralSupport.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstring>
Expand Down Expand Up @@ -705,7 +706,9 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
StringRef Param = Params->getParam(i)->getName();
if (Param.empty()) continue;
TOut << Param << " = ";
Args.get(i).print(Policy, TOut);
Args.get(i).print(
Policy, TOut,
TemplateParameterList::shouldIncludeTypeForArgument(Params, i));
TOut << ", ";
}
}
Expand All @@ -721,7 +724,7 @@ std::string PredefinedExpr::ComputeName(IdentKind IK, const Decl *CurrentDecl) {
StringRef Param = Params->getParam(i)->getName();
if (Param.empty()) continue;
TOut << Param << " = ";
Args->get(i).print(Policy, TOut);
Args->get(i).print(Policy, TOut, /*IncludeType*/ true);
TOut << ", ";
}
}
Expand Down Expand Up @@ -865,6 +868,76 @@ std::string FixedPointLiteral::getValueAsString(unsigned Radix) const {
return std::string(S.str());
}

void CharacterLiteral::print(unsigned Val, CharacterKind Kind,
raw_ostream &OS) {
switch (Kind) {
case CharacterLiteral::Ascii:
break; // no prefix.
case CharacterLiteral::Wide:
OS << 'L';
break;
case CharacterLiteral::UTF8:
OS << "u8";
break;
case CharacterLiteral::UTF16:
OS << 'u';
break;
case CharacterLiteral::UTF32:
OS << 'U';
break;
}

switch (Val) {
case '\\':
OS << "'\\\\'";
break;
case '\'':
OS << "'\\''";
break;
case '\a':
// TODO: K&R: the meaning of '\\a' is different in traditional C
OS << "'\\a'";
break;
case '\b':
OS << "'\\b'";
break;
// Nonstandard escape sequence.
/*case '\e':
OS << "'\\e'";
break;*/
case '\f':
OS << "'\\f'";
break;
case '\n':
OS << "'\\n'";
break;
case '\r':
OS << "'\\r'";
break;
case '\t':
OS << "'\\t'";
break;
case '\v':
OS << "'\\v'";
break;
default:
// A character literal might be sign-extended, which
// would result in an invalid \U escape sequence.
// FIXME: multicharacter literals such as '\xFF\xFF\xFF\xFF'
// are not correctly handled.
if ((Val & ~0xFFu) == ~0xFFu && Kind == CharacterLiteral::Ascii)
Val &= 0xFFu;
if (Val < 256 && isPrintable((unsigned char)Val))
OS << "'" << (char)Val << "'";
else if (Val < 256)
OS << "'\\x" << llvm::format("%02x", Val) << "'";
else if (Val <= 0xFFFF)
OS << "'\\u" << llvm::format("%04x", Val) << "'";
else
OS << "'\\U" << llvm::format("%08x", Val) << "'";
}
}

FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L)
: Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary), Loc(L) {
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/AST/NestedNameSpecifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,9 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
if (ResolveTemplateArguments && Record) {
// Print the type trait with resolved template parameters.
Record->printName(OS);
printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(),
Policy);
printTemplateArgumentList(
OS, Record->getTemplateArgs().asArray(), Policy,
Record->getSpecializedTemplate()->getTemplateParameters());
break;
}
const Type *T = getAsType();
Expand Down
Loading

0 comments on commit 99d63cc

Please sign in to comment.