Merge commit '60ea58923cedab42181297ba150cab731449fc67' into HEAD

This commit is contained in:
dotnet-bot 2016-02-15 05:54:30 -08:00
Родитель 6493123e67 60ea58923c
Коммит 11db0fc320
36 изменённых файлов: 617 добавлений и 332 удалений

Просмотреть файл

@ -666,7 +666,7 @@ Adding additional style options
===============================
Each additional style option adds costs to the clang-format project. Some of
these costs affect the clang-format developement itself, as we need to make
these costs affect the clang-format development itself, as we need to make
sure that any given combination of options work and that new features don't
break any of the existing options in any way. There are also costs for end users
as options become less discoverable and people have to think about and make a

Просмотреть файл

@ -32,7 +32,7 @@ when compiling your code.
On the other hand, Clang/LLVM is natively a cross-compiler, meaning that
one set of programs can compile to all targets by setting the ``-target``
option. That makes it a lot easier for programers wishing to compile to
option. That makes it a lot easier for programmers wishing to compile to
different platforms and architectures, and for compiler developers that
only have to maintain one build system, and for OS distributions, that
need only one set of main packages.

Просмотреть файл

@ -1857,7 +1857,7 @@ in the `ARM C Language Extensions Release 2.0
<http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf>`_.
Note that these intrinsics are implemented as motion barriers that block
reordering of memory accesses and side effect instructions. Other instructions
like simple arithmatic may be reordered around the intrinsic. If you expect to
like simple arithmetic may be reordered around the intrinsic. If you expect to
have no reordering at all, use inline assembly instead.
X86/X86-64 Language Extensions

Просмотреть файл

@ -110,8 +110,8 @@ Sancov matches these files using module names and binaries file names.
Action (required)
-print - Print coverage addresses
-covered-functions - Print all covered funcions.
-not-covered-functions - Print all not covered funcions.
-covered-functions - Print all covered functions.
-not-covered-functions - Print all not covered functions.
-html-report - Print HTML coverage report.
Options

Просмотреть файл

@ -124,6 +124,7 @@ public:
void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
raw_ostream &Out);
void mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD, raw_ostream &);
void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &);
virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0;

Просмотреть файл

@ -40,6 +40,7 @@ struct PrintingPolicy {
SuppressUnwrittenScope(false), SuppressInitializers(false),
ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
SuppressTemplateArgsInCXXConstructors(false),
Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false),
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
IncludeNewlines(true), MSVCFormatting(false) { }
@ -136,7 +137,11 @@ struct PrintingPolicy {
/// \brief When true, suppress printing of lifetime qualifier in
/// ARC.
unsigned SuppressLifetimeQualifiers : 1;
/// When true, suppresses printing template arguments in names of C++
/// constructors.
unsigned SuppressTemplateArgsInCXXConstructors : 1;
/// \brief Whether we can use 'bool' rather than '_Bool', even if the language
/// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
unsigned Bool : 1;

Просмотреть файл

@ -3673,6 +3673,19 @@ AST_MATCHER(QualType, isAnyCharacter) {
return Node->isAnyCharacterType();
}
//// \brief Matches QualType nodes that are of any pointer type.
///
/// Given
/// \code
/// int *i = nullptr;
/// int j;
/// \endcode
/// varDecl(hasType(isAnyPointer()))
/// matches "int *i", but not "int j".
AST_MATCHER(QualType, isAnyPointer) {
return Node->isAnyPointerType();
}
/// \brief Matches QualType nodes that are const-qualified, i.e., that
/// include "top-level" const.
///

Просмотреть файл

@ -0,0 +1,52 @@
//===- CodegenNameGenerator.h - Codegen name generation -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Determines the name that the symbol will get for code generation.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H
#define LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H
#include "clang/Basic/LLVM.h"
#include <memory>
#include <string>
#include <vector>
namespace clang {
class ASTContext;
class Decl;
namespace index {
class CodegenNameGenerator {
public:
explicit CodegenNameGenerator(ASTContext &Ctx);
~CodegenNameGenerator();
/// \returns true on failure to produce a name for the given decl, false on
/// success.
bool writeName(const Decl *D, raw_ostream &OS);
/// Version of \c writeName function that returns a string.
std::string getName(const Decl *D);
/// This can return multiple mangled names when applicable, e.g. for C++
/// constructors/destructors.
std::vector<std::string> getAllManglings(const Decl *D);
private:
struct Implementation;
std::unique_ptr<Implementation> Impl;
};
} // namespace index
} // namespace clang
#endif // LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H

Просмотреть файл

@ -13,6 +13,7 @@
#include "clang/Index/IndexSymbol.h"
namespace clang {
class ASTContext;
class DeclContext;
class Expr;
class FileID;
@ -33,6 +34,8 @@ public:
virtual ~IndexDataConsumer() {}
virtual void initialize(ASTContext &Ctx) {}
/// \returns true to continue indexing, or false to abort.
virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
ArrayRef<SymbolRelation> Relations,

Просмотреть файл

@ -16,6 +16,7 @@
namespace clang {
class Decl;
class LangOptions;
namespace index {
@ -111,6 +112,10 @@ SymbolInfo getSymbolInfo(const Decl *D);
void applyForEachSymbolRole(SymbolRoleSet Roles,
llvm::function_ref<void(SymbolRole)> Fn);
void printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS);
/// \returns true if no name was printed, false otherwise.
bool printSymbolName(const Decl *D, const LangOptions &LO, raw_ostream &OS);
StringRef getSymbolKindString(SymbolKind K);
StringRef getTemplateKindStr(SymbolCXXTemplateKind TK);
StringRef getSymbolLanguageString(SymbolLanguage K);

Просмотреть файл

@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
@ -140,6 +140,12 @@ static void printCXXConstructorDestructorName(QualType ClassType,
OS << *ClassRec->getDecl();
return;
}
if (Policy.SuppressTemplateArgsInCXXConstructors) {
if (auto *InjTy = ClassType->getAs<InjectedClassNameType>()) {
OS << *InjTy->getDecl();
return;
}
}
if (!Policy.LangOpts.CPlusPlus) {
// Passed policy is the default one from operator <<, use a C++ policy.
LangOptions LO;

Просмотреть файл

@ -254,11 +254,8 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
mangleFunctionBlock(*this, Buffer, BD, Out);
}
void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
raw_ostream &Out) {
SmallString<64> Name;
llvm::raw_svector_ostream OS(Name);
void MangleContext::mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD,
raw_ostream &OS) {
const ObjCContainerDecl *CD =
dyn_cast<ObjCContainerDecl>(MD->getDeclContext());
assert (CD && "Missing container decl in GetNameForMethod");
@ -268,6 +265,13 @@ void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
OS << ' ';
MD->getSelector().print(OS);
OS << ']';
}
void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
raw_ostream &Out) {
SmallString<64> Name;
llvm::raw_svector_ostream OS(Name);
mangleObjCMethodNameWithoutSize(MD, OS);
Out << OS.str().size() << OS.str();
}

Просмотреть файл

@ -264,6 +264,8 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(innerType);
REGISTER_MATCHER(integerLiteral);
REGISTER_MATCHER(isAnonymous);
REGISTER_MATCHER(isAnyCharacter);
REGISTER_MATCHER(isAnyPointer);
REGISTER_MATCHER(isArrow);
REGISTER_MATCHER(isBaseInitializer);
REGISTER_MATCHER(isCatchAll);

Просмотреть файл

@ -376,14 +376,23 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
OMPPrivateScope &PrivateScope) {
if (!HaveInsertPoint())
return false;
bool FirstprivateIsLastprivate = false;
llvm::DenseSet<const VarDecl *> Lastprivates;
for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
for (const auto *D : C->varlists())
Lastprivates.insert(
cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
}
llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
auto IRef = C->varlist_begin();
auto InitsRef = C->inits().begin();
for (auto IInit : C->private_copies()) {
auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
if (EmittedAsFirstprivate.count(OrigVD) == 0) {
EmittedAsFirstprivate.insert(OrigVD);
FirstprivateIsLastprivate =
FirstprivateIsLastprivate ||
(Lastprivates.count(OrigVD->getCanonicalDecl()) > 0);
if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
auto *VDInit = cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
bool IsRegistered;
@ -443,7 +452,7 @@ bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
++IRef, ++InitsRef;
}
}
return !EmittedAsFirstprivate.empty();
return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
}
void CodeGenFunction::EmitOMPPrivateClause(
@ -490,7 +499,6 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
QualType Type = VD->getType();
if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
// Get the address of the master variable. If we are emitting code with
// TLS support, the address is passed from the master as field in the
// captured declaration.
@ -964,12 +972,11 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
OMPPrivateScope PrivateScope(CGF);
bool Copyins = CGF.EmitOMPCopyinClause(S);
bool Firstprivates = CGF.EmitOMPFirstprivateClause(S, PrivateScope);
if (Copyins || Firstprivates) {
(void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
if (Copyins) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables or propagation master's thread
// values of threadprivate variables to local instances of that variables
// of all other implicit threads.
// propagation master's thread values of threadprivate variables to local
// instances of that variables of all other implicit threads.
CGF.CGM.getOpenMPRuntime().emitBarrierCall(
CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
/*ForceSimpleCall=*/true);
@ -1605,7 +1612,8 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(const OMPLoopDirective &S) {
OMPPrivateScope LoopScope(*this);
if (EmitOMPFirstprivateClause(S, LoopScope)) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables.
// initialization of firstprivate variables and post-update of
// lastprivate variables.
CGM.getOpenMPRuntime().emitBarrierCall(
*this, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
/*ForceSimpleCall=*/true);
@ -1804,7 +1812,8 @@ CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
CodeGenFunction::OMPPrivateScope LoopScope(CGF);
if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
// Emit implicit barrier to synchronize threads and avoid data races on
// initialization of firstprivate variables.
// initialization of firstprivate variables and post-update of lastprivate
// variables.
CGF.CGM.getOpenMPRuntime().emitBarrierCall(
CGF, S.getLocStart(), OMPD_unknown, /*EmitChecks=*/false,
/*ForceSimpleCall=*/true);
@ -1883,8 +1892,7 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
llvm::SmallVector<const Expr *, 8> SrcExprs;
llvm::SmallVector<const Expr *, 8> AssignmentOps;
// Check if there are any 'copyprivate' clauses associated with this
// 'single'
// construct.
// 'single' construct.
// Build a list of copyprivate variables along with helper expressions
// (<source>, <destination>, <destination>=<source> expressions)
for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) {
@ -1897,10 +1905,9 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
}
LexicalScope Scope(*this, S.getSourceRange());
// Emit code for 'single' region along with 'copyprivate' clauses
bool HasFirstprivates;
auto &&CodeGen = [&S, &HasFirstprivates](CodeGenFunction &CGF) {
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CodeGenFunction::OMPPrivateScope SingleScope(CGF);
HasFirstprivates = CGF.EmitOMPFirstprivateClause(S, SingleScope);
(void)CGF.EmitOMPFirstprivateClause(S, SingleScope);
CGF.EmitOMPPrivateClause(S, SingleScope);
(void)SingleScope.Privatize();
@ -1909,10 +1916,9 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getLocStart(),
CopyprivateVars, DestExprs, SrcExprs,
AssignmentOps);
// Emit an implicit barrier at the end (to avoid data race on firstprivate
// init or if no 'nowait' clause was specified and no 'copyprivate' clause).
if ((!S.getSingleClause<OMPNowaitClause>() || HasFirstprivates) &&
CopyprivateVars.empty()) {
// Emit an implicit barrier at the end (to avoid data race if no 'nowait'
// clause was specified and no 'copyprivate' clause).
if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
CGM.getOpenMPRuntime().emitBarrierCall(
*this, S.getLocStart(),
S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);

Просмотреть файл

@ -3128,6 +3128,22 @@ void FreeBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}
void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
bool Profiling = Args.hasArg(options::OPT_pg);
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
break;
case ToolChain::CST_Libstdcxx:
CmdArgs.push_back(Profiling ? "-lstdc++_p" : "-lstdc++");
break;
}
}
Tool *FreeBSD::buildAssembler() const {
return new tools::freebsd::Assembler(*this);
}

Просмотреть файл

@ -728,6 +728,8 @@ public:
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override;
bool isPIEDefault() const override;

Просмотреть файл

@ -1,16 +1,18 @@
set(LLVM_LINK_COMPONENTS
Core
Support
)
add_clang_library(clangIndex
CodegenNameGenerator.cpp
CommentToXML.cpp
USRGeneration.cpp
IndexBody.cpp
IndexDecl.cpp
IndexingAction.cpp
IndexingContext.cpp
IndexSymbol.cpp
IndexTypeSourceInfo.cpp
USRGeneration.cpp
ADDITIONAL_HEADERS
IndexingContext.h

Просмотреть файл

@ -0,0 +1,197 @@
//===- CodegenNameGenerator.cpp - Codegen name generation -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Determines the name that the symbol will get for code generation.
//
//===----------------------------------------------------------------------===//
#include "clang/Index/CodegenNameGenerator.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace clang::index;
struct CodegenNameGenerator::Implementation {
std::unique_ptr<MangleContext> MC;
llvm::DataLayout DL;
Implementation(ASTContext &Ctx)
: MC(Ctx.createMangleContext()),
DL(Ctx.getTargetInfo().getDataLayoutString()) {}
bool writeName(const Decl *D, raw_ostream &OS) {
// First apply frontend mangling.
SmallString<128> FrontendBuf;
llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDependentContext())
return true;
if (writeFuncOrVarName(FD, FrontendBufOS))
return true;
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
if (writeFuncOrVarName(VD, FrontendBufOS))
return true;
} else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
MC->mangleObjCMethodNameWithoutSize(MD, OS);
return false;
} else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
writeObjCClassName(ID, FrontendBufOS);
} else {
return true;
}
// Now apply backend mangling.
llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
return false;
}
std::string getName(const Decl *D) {
std::string Name;
{
llvm::raw_string_ostream OS(Name);
writeName(D, OS);
}
return Name;
}
std::vector<std::string> getAllManglings(const Decl *D) {
if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
return {};
const NamedDecl *ND = cast<NamedDecl>(D);
ASTContext &Ctx = ND->getASTContext();
std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
std::unique_ptr<llvm::DataLayout> DL(
new llvm::DataLayout(Ctx.getTargetInfo().getDataLayoutString()));
std::vector<std::string> Manglings;
auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
/*IsCSSMethod=*/true);
auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
return CC == DefaultCC;
};
if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
if (!CD->getParent()->isAbstract())
Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
} else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
if (DD->isVirtual())
Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
}
} else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
Manglings.emplace_back(getName(ND));
if (MD->isVirtual())
if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
for (const auto &T : *TIV)
Manglings.emplace_back(getMangledThunk(MD, T));
}
return Manglings;
}
private:
bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
if (MC->shouldMangleDeclName(D)) {
if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
MC->mangleCXXCtor(CtorD, Ctor_Complete, OS);
else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
MC->mangleCXXDtor(DtorD, Dtor_Complete, OS);
else
MC->mangleName(D, OS);
return false;
} else {
IdentifierInfo *II = D->getIdentifier();
if (!II)
return true;
OS << II->getName();
return false;
}
}
void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
OS << getClassSymbolPrefix();
OS << D->getObjCRuntimeNameAsString();
}
static StringRef getClassSymbolPrefix() {
return "OBJC_CLASS_$_";
}
std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);
if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
std::string BackendBuf;
llvm::raw_string_ostream BOS(BackendBuf);
llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
return BOS.str();
}
std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) {
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);
MC->mangleThunk(MD, T, FOS);
std::string BackendBuf;
llvm::raw_string_ostream BOS(BackendBuf);
llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
return BOS.str();
}
};
CodegenNameGenerator::CodegenNameGenerator(ASTContext &Ctx)
: Impl(new Implementation(Ctx)) {
}
CodegenNameGenerator::~CodegenNameGenerator() {
}
bool CodegenNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
return Impl->writeName(D, OS);
}
std::string CodegenNameGenerator::getName(const Decl *D) {
return Impl->getName(D);
}
std::vector<std::string> CodegenNameGenerator::getAllManglings(const Decl *D) {
return Impl->getAllManglings(D);
}

Просмотреть файл

@ -11,6 +11,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/PrettyPrinter.h"
using namespace clang;
using namespace clang::index;
@ -234,6 +235,24 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
});
}
bool index::printSymbolName(const Decl *D, const LangOptions &LO,
raw_ostream &OS) {
if (auto *ND = dyn_cast<NamedDecl>(D)) {
PrintingPolicy Policy(LO);
// Forward references can have different template argument names. Suppress
// the template argument names in constructors to make their name more
// stable.
Policy.SuppressTemplateArgsInCXXConstructors = true;
DeclarationName DeclName = ND->getDeclName();
if (DeclName.isEmpty())
return true;
DeclName.print(OS, Policy);
return false;
} else {
return true;
}
}
StringRef index::getSymbolKindString(SymbolKind K) {
switch (K) {
case SymbolKind::Unknown: return "<unknown>";
@ -266,6 +285,7 @@ StringRef index::getSymbolKindString(SymbolKind K) {
case SymbolKind::CXXTypeAlias: return "type-alias";
case SymbolKind::CXXInterface: return "c++-__interface";
}
llvm_unreachable("invalid symbol kind");
}
StringRef index::getTemplateKindStr(SymbolCXXTemplateKind TK) {
@ -275,6 +295,7 @@ StringRef index::getTemplateKindStr(SymbolCXXTemplateKind TK) {
case SymbolCXXTemplateKind::TemplatePartialSpecialization : return "TPS";
case SymbolCXXTemplateKind::TemplateSpecialization: return "TS";
}
llvm_unreachable("invalid template kind");
}
StringRef index::getSymbolLanguageString(SymbolLanguage K) {
@ -283,4 +304,5 @@ StringRef index::getSymbolLanguageString(SymbolLanguage K) {
case SymbolLanguage::ObjC: return "ObjC";
case SymbolLanguage::CXX: return "C++";
}
llvm_unreachable("invalid symbol language kind");
}

Просмотреть файл

@ -50,6 +50,7 @@ public:
protected:
void Initialize(ASTContext &Context) override {
IndexCtx.setASTContext(Context);
IndexCtx.getDataConsumer().initialize(Context);
}
bool HandleTopLevelDecl(DeclGroupRef DG) override {
@ -170,5 +171,6 @@ void index::indexASTUnit(ASTUnit &Unit,
IndexingOptions Opts) {
IndexingContext IndexCtx(Opts, *DataConsumer);
IndexCtx.setASTContext(Unit.getASTContext());
DataConsumer->initialize(Unit.getASTContext());
indexTranslationUnit(Unit, IndexCtx);
}

Просмотреть файл

@ -135,6 +135,7 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
case TSK_ExplicitInstantiationDefinition:
return true;
}
llvm_unreachable("invalid TemplateSpecializationKind");
}
bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {

Просмотреть файл

@ -210,7 +210,12 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
VisitTemplateParameterList(FunTmpl->getTemplateParameters());
} else
Out << "@F@";
D->printName(Out);
PrintingPolicy Policy(Context->getLangOpts());
// Forward references can have different template argument names. Suppress the
// template argument names in constructors to make their USR more stable.
Policy.SuppressTemplateArgsInCXXConstructors = true;
D->getDeclName().print(Out, Policy);
ASTContext &Ctx = *Context;
if (!Ctx.getLangOpts().CPlusPlus || D->isExternC())

Просмотреть файл

@ -5818,10 +5818,12 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
//===--- CHECK: Return Address of Stack Variable --------------------------===//
static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
Decl *ParentDecl);
static Expr *EvalAddr(Expr* E, SmallVectorImpl<DeclRefExpr *> &refVars,
Decl *ParentDecl);
static const Expr *EvalVal(const Expr *E,
SmallVectorImpl<const DeclRefExpr *> &refVars,
const Decl *ParentDecl);
static const Expr *EvalAddr(const Expr *E,
SmallVectorImpl<const DeclRefExpr *> &refVars,
const Decl *ParentDecl);
/// CheckReturnStackAddr - Check if a return statement returns the address
/// of a stack variable.
@ -5829,8 +5831,8 @@ static void
CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
SourceLocation ReturnLoc) {
Expr *stackE = nullptr;
SmallVector<DeclRefExpr *, 8> refVars;
const Expr *stackE = nullptr;
SmallVector<const DeclRefExpr *, 8> refVars;
// Perform checking for returned stack addresses, local blocks,
// label addresses or references to temporaries.
@ -5858,7 +5860,8 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
diagRange = refVars[0]->getSourceRange();
}
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var.
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) {
// address of local var
S.Diag(diagLoc, diag::warn_ret_stack_addr_ref) << lhsType->isReferenceType()
<< DR->getDecl()->getDeclName() << diagRange;
} else if (isa<BlockExpr>(stackE)) { // local block.
@ -5873,12 +5876,12 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
// Display the "trail" of reference variables that we followed until we
// found the problematic expression using notes.
for (unsigned i = 0, e = refVars.size(); i != e; ++i) {
VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl());
const VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl());
// If this var binds to another reference var, show the range of the next
// var, otherwise the var binds to the problematic expression, in which case
// show the range of the expression.
SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange()
: stackE->getSourceRange();
SourceRange range = (i < e - 1) ? refVars[i + 1]->getSourceRange()
: stackE->getSourceRange();
S.Diag(VD->getLocation(), diag::note_ref_var_local_bind)
<< VD->getDeclName() << range;
}
@ -5910,8 +5913,9 @@ CheckReturnStackAddr(Sema &S, Expr *RetValExp, QualType lhsType,
/// * arbitrary interplay between "&" and "*" operators
/// * pointer arithmetic from an address of a stack variable
/// * taking the address of an array element where the array is on the stack
static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
Decl *ParentDecl) {
static const Expr *EvalAddr(const Expr *E,
SmallVectorImpl<const DeclRefExpr *> &refVars,
const Decl *ParentDecl) {
if (E->isTypeDependent())
return nullptr;
@ -5928,13 +5932,13 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
// EvalAddr and EvalVal appropriately.
switch (E->getStmtClass()) {
case Stmt::DeclRefExprClass: {
DeclRefExpr *DR = cast<DeclRefExpr>(E);
const DeclRefExpr *DR = cast<DeclRefExpr>(E);
// If we leave the immediate function, the lifetime isn't about to end.
if (DR->refersToEnclosingVariableOrCapture())
return nullptr;
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
if (const VarDecl *V = dyn_cast<VarDecl>(DR->getDecl()))
// If this is a reference variable, follow through to the expression that
// it points to.
if (V->hasLocalStorage() &&
@ -5950,44 +5954,44 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
case Stmt::UnaryOperatorClass: {
// The only unary operator that make sense to handle here
// is AddrOf. All others don't make sense as pointers.
UnaryOperator *U = cast<UnaryOperator>(E);
const UnaryOperator *U = cast<UnaryOperator>(E);
if (U->getOpcode() == UO_AddrOf)
return EvalVal(U->getSubExpr(), refVars, ParentDecl);
else
return nullptr;
return nullptr;
}
case Stmt::BinaryOperatorClass: {
// Handle pointer arithmetic. All other binary operators are not valid
// in this context.
BinaryOperator *B = cast<BinaryOperator>(E);
const BinaryOperator *B = cast<BinaryOperator>(E);
BinaryOperatorKind op = B->getOpcode();
if (op != BO_Add && op != BO_Sub)
return nullptr;
Expr *Base = B->getLHS();
const Expr *Base = B->getLHS();
// Determine which argument is the real pointer base. It could be
// the RHS argument instead of the LHS.
if (!Base->getType()->isPointerType()) Base = B->getRHS();
if (!Base->getType()->isPointerType())
Base = B->getRHS();
assert (Base->getType()->isPointerType());
assert(Base->getType()->isPointerType());
return EvalAddr(Base, refVars, ParentDecl);
}
// For conditional operators we need to see if either the LHS or RHS are
// valid DeclRefExpr*s. If one of them is valid, we return it.
case Stmt::ConditionalOperatorClass: {
ConditionalOperator *C = cast<ConditionalOperator>(E);
const ConditionalOperator *C = cast<ConditionalOperator>(E);
// Handle the GNU extension for missing LHS.
// FIXME: That isn't a ConditionalOperator, so doesn't get here.
if (Expr *LHSExpr = C->getLHS()) {
if (const Expr *LHSExpr = C->getLHS()) {
// In C++, we can have a throw-expression, which has 'void' type.
if (!LHSExpr->getType()->isVoidType())
if (Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl))
if (const Expr *LHS = EvalAddr(LHSExpr, refVars, ParentDecl))
return LHS;
}
@ -6020,7 +6024,7 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
case Stmt::CXXDynamicCastExprClass:
case Stmt::CXXConstCastExprClass:
case Stmt::CXXReinterpretCastExprClass: {
Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
const Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
switch (cast<CastExpr>(E)->getCastKind()) {
case CK_LValueToRValue:
case CK_NoOp:
@ -6050,13 +6054,12 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
}
case Stmt::MaterializeTemporaryExprClass:
if (Expr *Result = EvalAddr(
cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
refVars, ParentDecl))
if (const Expr *Result =
EvalAddr(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
refVars, ParentDecl))
return Result;
return E;
// Everything else: we simply don't reason about them.
default:
return nullptr;
@ -6065,141 +6068,147 @@ static Expr *EvalAddr(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
/// EvalVal - This function is complements EvalAddr in the mutual recursion.
/// See the comments for EvalAddr for more details.
static Expr *EvalVal(Expr *E, SmallVectorImpl<DeclRefExpr *> &refVars,
Decl *ParentDecl) {
do {
// We should only be called for evaluating non-pointer expressions, or
// expressions with a pointer type that are not used as references but instead
// are l-values (e.g., DeclRefExpr with a pointer type).
static const Expr *EvalVal(const Expr *E,
SmallVectorImpl<const DeclRefExpr *> &refVars,
const Decl *ParentDecl) {
do {
// We should only be called for evaluating non-pointer expressions, or
// expressions with a pointer type that are not used as references but
// instead
// are l-values (e.g., DeclRefExpr with a pointer type).
// Our "symbolic interpreter" is just a dispatch off the currently
// viewed AST node. We then recursively traverse the AST by calling
// EvalAddr and EvalVal appropriately.
// Our "symbolic interpreter" is just a dispatch off the currently
// viewed AST node. We then recursively traverse the AST by calling
// EvalAddr and EvalVal appropriately.
E = E->IgnoreParens();
switch (E->getStmtClass()) {
case Stmt::ImplicitCastExprClass: {
ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
if (IE->getValueKind() == VK_LValue) {
E = IE->getSubExpr();
continue;
}
return nullptr;
}
case Stmt::ExprWithCleanupsClass:
return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,ParentDecl);
case Stmt::DeclRefExprClass: {
// When we hit a DeclRefExpr we are looking at code that refers to a
// variable's name. If it's not a reference variable we check if it has
// local storage within the function, and if so, return the expression.
DeclRefExpr *DR = cast<DeclRefExpr>(E);
// If we leave the immediate function, the lifetime isn't about to end.
if (DR->refersToEnclosingVariableOrCapture())
E = E->IgnoreParens();
switch (E->getStmtClass()) {
case Stmt::ImplicitCastExprClass: {
const ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E);
if (IE->getValueKind() == VK_LValue) {
E = IE->getSubExpr();
continue;
}
return nullptr;
}
if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
// Check if it refers to itself, e.g. "int& i = i;".
if (V == ParentDecl)
return DR;
case Stmt::ExprWithCleanupsClass:
return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars,
ParentDecl);
if (V->hasLocalStorage()) {
if (!V->getType()->isReferenceType())
case Stmt::DeclRefExprClass: {
// When we hit a DeclRefExpr we are looking at code that refers to a
// variable's name. If it's not a reference variable we check if it has
// local storage within the function, and if so, return the expression.
const DeclRefExpr *DR = cast<DeclRefExpr>(E);
// If we leave the immediate function, the lifetime isn't about to end.
if (DR->refersToEnclosingVariableOrCapture())
return nullptr;
if (const VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) {
// Check if it refers to itself, e.g. "int& i = i;".
if (V == ParentDecl)
return DR;
// Reference variable, follow through to the expression that
// it points to.
if (V->hasInit()) {
// Add the reference variable to the "trail".
refVars.push_back(DR);
return EvalVal(V->getInit(), refVars, V);
if (V->hasLocalStorage()) {
if (!V->getType()->isReferenceType())
return DR;
// Reference variable, follow through to the expression that
// it points to.
if (V->hasInit()) {
// Add the reference variable to the "trail".
refVars.push_back(DR);
return EvalVal(V->getInit(), refVars, V);
}
}
}
return nullptr;
}
return nullptr;
}
case Stmt::UnaryOperatorClass: {
// The only unary operator that make sense to handle here
// is Deref. All others don't resolve to a "name." This includes
// handling all sorts of rvalues passed to a unary operator.
const UnaryOperator *U = cast<UnaryOperator>(E);
case Stmt::UnaryOperatorClass: {
// The only unary operator that make sense to handle here
// is Deref. All others don't resolve to a "name." This includes
// handling all sorts of rvalues passed to a unary operator.
UnaryOperator *U = cast<UnaryOperator>(E);
if (U->getOpcode() == UO_Deref)
return EvalAddr(U->getSubExpr(), refVars, ParentDecl);
if (U->getOpcode() == UO_Deref)
return EvalAddr(U->getSubExpr(), refVars, ParentDecl);
return nullptr;
}
return nullptr;
}
case Stmt::ArraySubscriptExprClass: {
// Array subscripts are potential references to data on the stack. We
// retrieve the DeclRefExpr* for the array variable if it indeed
// has local storage.
const auto *ASE = cast<ArraySubscriptExpr>(E);
if (ASE->isTypeDependent())
return nullptr;
return EvalAddr(ASE->getBase(), refVars, ParentDecl);
}
case Stmt::ArraySubscriptExprClass: {
// Array subscripts are potential references to data on the stack. We
// retrieve the DeclRefExpr* for the array variable if it indeed
// has local storage.
return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars,ParentDecl);
}
case Stmt::OMPArraySectionExprClass: {
return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars,
ParentDecl);
}
case Stmt::OMPArraySectionExprClass: {
return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars,
ParentDecl);
}
case Stmt::ConditionalOperatorClass: {
// For conditional operators we need to see if either the LHS or RHS are
// non-NULL Expr's. If one is non-NULL, we return it.
const ConditionalOperator *C = cast<ConditionalOperator>(E);
case Stmt::ConditionalOperatorClass: {
// For conditional operators we need to see if either the LHS or RHS are
// non-NULL Expr's. If one is non-NULL, we return it.
ConditionalOperator *C = cast<ConditionalOperator>(E);
// Handle the GNU extension for missing LHS.
if (const Expr *LHSExpr = C->getLHS()) {
// In C++, we can have a throw-expression, which has 'void' type.
if (!LHSExpr->getType()->isVoidType())
if (const Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl))
return LHS;
}
// Handle the GNU extension for missing LHS.
if (Expr *LHSExpr = C->getLHS()) {
// In C++, we can have a throw-expression, which has 'void' type.
if (!LHSExpr->getType()->isVoidType())
if (Expr *LHS = EvalVal(LHSExpr, refVars, ParentDecl))
return LHS;
if (C->getRHS()->getType()->isVoidType())
return nullptr;
return EvalVal(C->getRHS(), refVars, ParentDecl);
}
// In C++, we can have a throw-expression, which has 'void' type.
if (C->getRHS()->getType()->isVoidType())
return nullptr;
// Accesses to members are potential references to data on the stack.
case Stmt::MemberExprClass: {
const MemberExpr *M = cast<MemberExpr>(E);
return EvalVal(C->getRHS(), refVars, ParentDecl);
}
// Check for indirect access. We only want direct field accesses.
if (M->isArrow())
return nullptr;
// Accesses to members are potential references to data on the stack.
case Stmt::MemberExprClass: {
MemberExpr *M = cast<MemberExpr>(E);
// Check whether the member type is itself a reference, in which case
// we're not going to refer to the member, but to what the member refers
// to.
if (M->getMemberDecl()->getType()->isReferenceType())
return nullptr;
// Check for indirect access. We only want direct field accesses.
if (M->isArrow())
return nullptr;
return EvalVal(M->getBase(), refVars, ParentDecl);
}
// Check whether the member type is itself a reference, in which case
// we're not going to refer to the member, but to what the member refers to.
if (M->getMemberDecl()->getType()->isReferenceType())
return nullptr;
return EvalVal(M->getBase(), refVars, ParentDecl);
}
case Stmt::MaterializeTemporaryExprClass:
if (Expr *Result = EvalVal(
cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
refVars, ParentDecl))
return Result;
return E;
default:
// Check that we don't return or take the address of a reference to a
// temporary. This is only useful in C++.
if (!E->isTypeDependent() && E->isRValue())
case Stmt::MaterializeTemporaryExprClass:
if (const Expr *Result =
EvalVal(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr(),
refVars, ParentDecl))
return Result;
return E;
// Everything else: we simply don't reason about them.
return nullptr;
}
} while (true);
default:
// Check that we don't return or take the address of a reference to a
// temporary. This is only useful in C++.
if (!E->isTypeDependent() && E->isRValue())
return E;
// Everything else: we simply don't reason about them.
return nullptr;
}
} while (true);
}
void

Просмотреть файл

@ -2,5 +2,12 @@
// RUN: | FileCheck --check-prefix=CHECK-TEN %s
// RUN: %clangxx %s -### -o %t.o -target amd64-unknown-freebsd9.2 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NINE %s
// CHECK-TEN: -lc++
// CHECK-NINE: -lstdc++
// CHECK-TEN: "-lc++" "-lm"
// CHECK-NINE: "-lstdc++" "-lm"
// RUN: %clangxx %s -### -pg -o %t.o -target amd64-unknown-freebsd10.0 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-PG-TEN %s
// RUN: %clangxx %s -### -pg -o %t.o -target amd64-unknown-freebsd9.2 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-PG-NINE %s
// CHECK-PG-TEN: "-lc++_p" "-lm_p"
// CHECK-PG-NINE: "-lstdc++_p" "-lm_p"

Просмотреть файл

@ -0,0 +1,9 @@
// RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
template <typename TemplArg>
class TemplCls {
// CHECK: [[@LINE-1]]:7 | c++-class/C++ | TemplCls | c:@ST>1#T@TemplCls | <no-cgname> | Def | rel: 0
TemplCls(int x);
// CHECK: [[@LINE-1]]:3 | constructor/C++ | TemplCls | c:@ST>1#T@TemplCls@F@TemplCls#I# | <no-cgname> | Decl/RelChild | rel: 1
// CHECK-NEXT: RelChild | TemplCls | c:@ST>1#T@TemplCls
};

Просмотреть файл

@ -1,8 +1,8 @@
// RUN: c-index-test core -print-source-symbols -- %s | FileCheck %s
// RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s
@interface Base
// CHECK: [[@LINE-1]]:12 | objc-class/ObjC | Base | c:objc(cs)Base | Decl | rel: 0
// CHECK: [[@LINE-1]]:12 | objc-class/ObjC | Base | c:objc(cs)Base | _OBJC_CLASS_$_Base | Decl | rel: 0
-(void)meth;
// CHECK: [[@LINE-1]]:1 | objc-instance-method/ObjC | meth | c:objc(cs)Base(im)meth | Decl/Dyn/RelChild | rel: 1
// CHECK: [[@LINE-1]]:1 | objc-instance-method/ObjC | meth | c:objc(cs)Base(im)meth | -[Base meth] | Decl/Dyn/RelChild | rel: 1
// CHECK-NEXT: RelChild | Base | c:objc(cs)Base
@end

Просмотреть файл

@ -95,7 +95,7 @@ int main() {
// LAMBDA: [[SIVAR2_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR2_PRIVATE_ADDR_REF]]
// LAMBDA: store i{{[0-9]+}} [[SIVAR2_VAL]], i{{[0-9]+}}* [[SIVAR2_PRIVATE_ADDR]]
// LAMBDA: call void @__kmpc_barrier(
// LAMBDA-NOT: call void @__kmpc_barrier(
g = 1;
g1 = 1;
sivar = 2;
@ -158,7 +158,7 @@ int main() {
// BLOCKS: [[SIVAR2_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF_ADDRR]]
// BLOCKS: store i{{[0-9]+}} {{.+}}, i{{[0-9]+}}* [[SIVAR2_PRIVATE_ADDR]]
// BLOCKS: call void @__kmpc_barrier(
// BLOCKS-NOT: call void @__kmpc_barrier(
g = 1;
g1 =1;
sivar = 2;
@ -246,7 +246,7 @@ int main() {
// CHECK: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIV]]
// Synchronization for initialization.
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK-NOT: call void @__kmpc_barrier(
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call void @__kmpc_for_static_fini(
@ -310,10 +310,8 @@ int main() {
// CHECK: call {{.*}} [[S_INT_TY_COPY_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]* {{.*}} [[VAR_REF]], [[ST_TY]]* [[ST_TY_TEMP]])
// CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
// Synchronization for initialization.
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// No synchronization for initialization.
// CHECK-NOT: call void @__kmpc_barrier(
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call void @__kmpc_for_static_fini(

Просмотреть файл

@ -31,7 +31,6 @@ struct S {
// CHECK-DAG: [[S_FLOAT_TY:%.+]] = type { float }
// CHECK-DAG: [[S_INT_TY:%.+]] = type { i{{[0-9]+}} }
// CHECK-DAG: [[ST_TY:%.+]] = type { i{{[0-9]+}}, i{{[0-9]+}} }
// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
template <typename T>
T tmain() {
@ -70,7 +69,7 @@ int main() {
// LAMBDA: store i{{[0-9]+}} [[G_VAL]], i{{[0-9]+}}* [[G_PRIVATE_ADDR]], align 128
// LAMBDA: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF]]
// LAMBDA: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]]
// LAMBDA: call {{.*}}void @__kmpc_barrier(
// LAMBDA-NOT: call {{.*}}void @__kmpc_barrier(
g = 1;
sivar = 2;
// LAMBDA: store i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
@ -115,7 +114,7 @@ int main() {
// BLOCK: [[SIVAR_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[SIVAR_REF_ADDR]]
// BLOCKS: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR_REF]],
// BLOCKS: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIVATE_ADDR]],
// BLOCKS: call {{.*}}void @__kmpc_barrier(
// BLOCKS-NOT: call {{.*}}void @__kmpc_barrier(
g = 1;
sivar = 2;
// BLOCKS: store i{{[0-9]+}} 1, i{{[0-9]+}}* [[G_PRIVATE_ADDR]],
@ -244,9 +243,7 @@ int main() {
// CHECK: call {{.*}} [[ST_TY_DEFAULT_CONSTR]]([[ST_TY]]* [[ST_TY_TEMP:%.+]])
// CHECK: call {{.*}} [[S_INT_TY_COPY_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]* {{.*}} [[VAR_REF]], [[ST_TY]]* [[ST_TY_TEMP]])
// CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
// CHECK: call {{.*}}void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK-NOT: call {{.*}}void @__kmpc_barrier(
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]* [[VAR_PRIV]])
// CHECK-DAG: call {{.*}} [[S_INT_TY_DESTR]]([[S_INT_TY]]*
// CHECK: ret void

Просмотреть файл

@ -59,7 +59,6 @@ S<float> s_arr[] = {1, 2};
// CHECK-DAG: [[VAR:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
S<float> var(3);
// CHECK-DAG: [[SIVAR:@.+]] = internal global i{{[0-9]+}} 0,
// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
// CHECK-DAG: [[SECTIONS_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 194, i32 0, i32 0, i8*
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
@ -94,7 +93,7 @@ int main() {
// LAMBDA: [[SIVAR1_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR1_REF]]
// LAMBDA: store i{{[0-9]+}} [[SIVAR1_VAL]], i{{[0-9]+}}* [[SIVAR1_PRIVATE_ADDR]]
// LAMBDA: call void @__kmpc_barrier(
// LAMBDA-NOT: call void @__kmpc_barrier(
{
g = 1;
sivar = 10;
@ -154,7 +153,7 @@ int main() {
// BLOCKS: [[SIVAR1_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR1_REF]],
// BLOCKS: store i{{[0-9]+}} [[SIVAR1_VAL]], i{{[0-9]+}}* [[SIVAR1_PRIVATE_ADDR]],
// BLOCKS: call void @__kmpc_barrier(
// BLOCKS-NOT: call void @__kmpc_barrier(
{
g = 1;
sivar = 10;
@ -242,7 +241,7 @@ int main() {
// CHECK: [[SIVAR_VAL:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[SIVAR]],
// CHECK: store i{{[0-9]+}} [[SIVAR_VAL]], i{{[0-9]+}}* [[SIVAR_PRIV]],
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK-NOT: call void @__kmpc_barrier(
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call void @__kmpc_for_static_fini(
@ -304,10 +303,8 @@ int main() {
// CHECK: call {{.*}} [[S_INT_TY_COPY_CONSTR]]([[S_INT_TY]]* [[VAR_PRIV]], [[S_INT_TY]]* {{.*}} [[VAR_REF]], [[ST_TY]]* [[ST_TY_TEMP]])
// CHECK: call {{.*}} [[ST_TY_DESTR]]([[ST_TY]]* [[ST_TY_TEMP]])
// Synchronization for initialization.
// CHECK: [[GTID_REF:%.+]] = load i{{[0-9]+}}*, i{{[0-9]+}}** [[GTID_ADDR_ADDR]]
// CHECK: [[GTID:%.+]] = load i{{[0-9]+}}, i{{[0-9]+}}* [[GTID_REF]]
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// No synchronization for initialization.
// CHECK-NOT: call void @__kmpc_barrier(
// CHECK: call void @__kmpc_for_static_init_4(
// CHECK: call void @__kmpc_for_static_fini(

Просмотреть файл

@ -57,7 +57,6 @@ int vec[] = {1, 2};
S<float> s_arr[] = {1, 2};
// CHECK-DAG: [[VAR:@.+]] = global [[S_FLOAT_TY]] zeroinitializer,
S<float> var(3);
// CHECK-DAG: [[IMPLICIT_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 66, i32 0, i32 0, i8*
// CHECK-DAG: [[SINGLE_BARRIER_LOC:@.+]] = private unnamed_addr constant %{{.+}} { i32 0, i32 322, i32 0, i32 0, i8*
// CHECK: call {{.*}} [[S_FLOAT_TY_DEF_CONSTR:@.+]]([[S_FLOAT_TY]]* [[TEST]])
@ -215,7 +214,7 @@ int main() {
// CHECK-DAG: call {{.*}} [[S_FLOAT_TY_DESTR]]([[S_FLOAT_TY]]*
// CHECK: call void @__kmpc_end_single(
// CHECK: call void @__kmpc_barrier(%{{.+}}* [[IMPLICIT_BARRIER_LOC]], i{{[0-9]+}} [[GTID]])
// CHECK-NOT: call void @__kmpc_barrier(
// CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT:@.+]]()

Просмотреть файл

@ -0,0 +1,22 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -std=c++11 %s
// expected-no-diagnostics
namespace PR26599 {
template <typename>
struct S;
struct I {};
template <typename T>
void *&non_pointer() {
void *&r = S<T>()[I{}];
return r;
}
template <typename T>
void *&pointer() {
void *&r = S<T>()[nullptr];
return r;
}
}

Просмотреть файл

@ -22,6 +22,9 @@ if (LLVM_BUILD_STATIC)
else()
target_link_libraries(c-index-test
libclang
clangAST
clangBasic
clangFrontend
clangIndex
)
endif()

Просмотреть файл

@ -14,6 +14,7 @@
#include "clang/Index/IndexingAction.h"
#include "clang/Index/IndexDataConsumer.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Index/CodegenNameGenerator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
@ -60,11 +61,16 @@ namespace {
class PrintIndexDataConsumer : public IndexDataConsumer {
raw_ostream &OS;
std::unique_ptr<CodegenNameGenerator> CGNameGen;
public:
PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) {
}
void initialize(ASTContext &Ctx) override {
CGNameGen.reset(new CodegenNameGenerator(Ctx));
}
bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
ArrayRef<SymbolRelation> Relations,
FileID FID, unsigned Offset,
@ -82,6 +88,10 @@ public:
printSymbolNameAndUSR(D, Ctx, OS);
OS << " | ";
if (CGNameGen->writeName(D, OS))
OS << "<no-cgname>";
OS << " | ";
printSymbolRoles(Roles, OS);
OS << " | ";
@ -123,9 +133,8 @@ static bool printSourceSymbols(ArrayRef<const char *> Args) {
/*WrappedAction=*/nullptr);
auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
ASTUnit *Unit =
ASTUnit::LoadFromCompilerInvocationAction(CInvok.get(), PCHContainerOps,
Diags, IndexAction.get());
std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
CInvok.get(), PCHContainerOps, Diags, IndexAction.get()));
if (!Unit)
return true;
@ -147,10 +156,7 @@ static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS) {
static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
raw_ostream &OS) {
if (auto *ND = dyn_cast<NamedDecl>(D)) {
PrintingPolicy PrintPolicy(Ctx.getLangOpts());
ND->getDeclName().print(OS, PrintPolicy);
} else {
if (printSymbolName(D, Ctx.getLangOpts(), OS)) {
OS << "<no-name>";
}
OS << " | ";

Просмотреть файл

@ -22,17 +22,15 @@
#include "CXType.h"
#include "CursorVisitor.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticCategories.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Index/CodegenNameGenerator.h"
#include "clang/Index/CommentToXML.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Lexer.h"
@ -43,8 +41,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/Format.h"
@ -3976,59 +3972,6 @@ static SourceLocation getLocationFromExpr(const Expr *E) {
return E->getLocStart();
}
static std::string getMangledStructor(std::unique_ptr<MangleContext> &M,
std::unique_ptr<llvm::DataLayout> &DL,
const NamedDecl *ND,
unsigned StructorType) {
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);
if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
M->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
M->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
std::string BackendBuf;
llvm::raw_string_ostream BOS(BackendBuf);
llvm::Mangler::getNameWithPrefix(BOS, llvm::Twine(FOS.str()), *DL);
return BOS.str();
}
static std::string getMangledName(std::unique_ptr<MangleContext> &M,
std::unique_ptr<llvm::DataLayout> &DL,
const NamedDecl *ND) {
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);
M->mangleName(ND, FOS);
std::string BackendBuf;
llvm::raw_string_ostream BOS(BackendBuf);
llvm::Mangler::getNameWithPrefix(BOS, llvm::Twine(FOS.str()), *DL);
return BOS.str();
}
static std::string getMangledThunk(std::unique_ptr<MangleContext> &M,
std::unique_ptr<llvm::DataLayout> &DL,
const CXXMethodDecl *MD,
const ThunkInfo &T) {
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);
M->mangleThunk(MD, T, FOS);
std::string BackendBuf;
llvm::raw_string_ostream BOS(BackendBuf);
llvm::Mangler::getNameWithPrefix(BOS, llvm::Twine(FOS.str()), *DL);
return BOS.str();
}
extern "C" {
unsigned clang_visitChildren(CXCursor parent,
@ -4377,29 +4320,9 @@ CXString clang_Cursor_getMangling(CXCursor C) {
if (!D || !(isa<FunctionDecl>(D) || isa<VarDecl>(D)))
return cxstring::createEmpty();
// First apply frontend mangling.
const NamedDecl *ND = cast<NamedDecl>(D);
ASTContext &Ctx = ND->getASTContext();
std::unique_ptr<MangleContext> MC(Ctx.createMangleContext());
std::string FrontendBuf;
llvm::raw_string_ostream FrontendBufOS(FrontendBuf);
if (MC->shouldMangleDeclName(ND)) {
MC->mangleName(ND, FrontendBufOS);
} else {
ND->printName(FrontendBufOS);
}
// Now apply backend mangling.
std::unique_ptr<llvm::DataLayout> DL(
new llvm::DataLayout(Ctx.getTargetInfo().getDataLayoutString()));
std::string FinalBuf;
llvm::raw_string_ostream FinalBufOS(FinalBuf);
llvm::Mangler::getNameWithPrefix(FinalBufOS, llvm::Twine(FrontendBufOS.str()),
*DL);
return cxstring::createDup(FinalBufOS.str());
ASTContext &Ctx = D->getASTContext();
index::CodegenNameGenerator CGNameGen(Ctx);
return cxstring::createDup(CGNameGen.getName(D));
}
CXStringSet *clang_Cursor_getCXXManglings(CXCursor C) {
@ -4410,49 +4333,9 @@ CXStringSet *clang_Cursor_getCXXManglings(CXCursor C) {
if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
return nullptr;
const NamedDecl *ND = cast<NamedDecl>(D);
ASTContext &Ctx = ND->getASTContext();
std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
std::unique_ptr<llvm::DataLayout> DL(
new llvm::DataLayout(Ctx.getTargetInfo().getDataLayoutString()));
std::vector<std::string> Manglings;
auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
/*IsCSSMethod=*/true);
auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
return CC == DefaultCC;
};
if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
Manglings.emplace_back(getMangledStructor(M, DL, CD, Ctor_Base));
if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
if (!CD->getParent()->isAbstract())
Manglings.emplace_back(getMangledStructor(M, DL, CD, Ctor_Complete));
if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
Manglings.emplace_back(getMangledStructor(M, DL, CD,
Ctor_DefaultClosure));
} else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
Manglings.emplace_back(getMangledStructor(M, DL, DD, Dtor_Base));
if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
Manglings.emplace_back(getMangledStructor(M, DL, DD, Dtor_Complete));
if (DD->isVirtual())
Manglings.emplace_back(getMangledStructor(M, DL, DD, Dtor_Deleting));
}
} else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
Manglings.emplace_back(getMangledName(M, DL, ND));
if (MD->isVirtual())
if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
for (const auto &T : *TIV)
Manglings.emplace_back(getMangledThunk(M, DL, MD, T));
}
ASTContext &Ctx = D->getASTContext();
index::CodegenNameGenerator CGNameGen(Ctx);
std::vector<std::string> Manglings = CGNameGen.getAllManglings(D);
return cxstring::createSet(Manglings);
}

Просмотреть файл

@ -1263,6 +1263,7 @@ static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K) {
case SymbolKind::CXXTypeAlias: return CXIdxEntity_CXXTypeAlias;
case SymbolKind::CXXInterface: return CXIdxEntity_CXXInterface;
}
llvm_unreachable("invalid symbol kind");
}
static CXIdxEntityCXXTemplateKind
@ -1275,6 +1276,7 @@ getEntityKindFromSymbolCXXTemplateKind(SymbolCXXTemplateKind K) {
case SymbolCXXTemplateKind::TemplateSpecialization:
return CXIdxEntity_TemplateSpecialization;
}
llvm_unreachable("invalid template kind");
}
static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
@ -1283,4 +1285,5 @@ static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC;
case SymbolLanguage::CXX: return CXIdxEntityLang_CXX;
}
llvm_unreachable("invalid symbol language");
}

Просмотреть файл

@ -1479,6 +1479,14 @@ TEST(IsInteger, ReportsNoFalsePositives) {
to(varDecl(hasType(isInteger()))))))));
}
TEST(IsAnyPointer, MatchesPointers) {
EXPECT_TRUE(matches("int* i = nullptr;", varDecl(hasType(isAnyPointer()))));
}
TEST(IsAnyPointer, ReportsNoFalsePositives) {
EXPECT_TRUE(notMatches("int i = 0;", varDecl(hasType(isAnyPointer()))));
}
TEST(IsAnyCharacter, MatchesCharacters) {
EXPECT_TRUE(matches("char i = 0;", varDecl(hasType(isAnyCharacter()))));
}