2 changes: 1 addition & 1 deletion clang/include/clang/Lex/ExternalPreprocessorSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ExternalPreprocessorSource {
virtual void ReadDefinedMacros() = 0;

/// Update an out-of-date identifier.
virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0;
virtual void updateOutOfDateIdentifier(const IdentifierInfo &II) = 0;

/// Return the identifier associated with the given ID number.
///
Expand Down
24 changes: 13 additions & 11 deletions clang/include/clang/Lex/HeaderSearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -547,14 +547,15 @@ class HeaderSearch {
/// Return whether the specified file is a normal header,
/// a system header, or a C++ friendly system header.
SrcMgr::CharacteristicKind getFileDirFlavor(FileEntryRef File) {
return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo;
if (const HeaderFileInfo *HFI = getExistingFileInfo(File))
return (SrcMgr::CharacteristicKind)HFI->DirInfo;
return (SrcMgr::CharacteristicKind)HeaderFileInfo().DirInfo;
}

/// Mark the specified file as a "once only" file due to
/// \#pragma once.
void MarkFileIncludeOnce(FileEntryRef File) {
HeaderFileInfo &FI = getFileInfo(File);
FI.isPragmaOnce = true;
getFileInfo(File).isPragmaOnce = true;
}

/// Mark the specified file as a system header, e.g. due to
Expand Down Expand Up @@ -834,16 +835,17 @@ class HeaderSearch {

unsigned header_file_size() const { return FileInfo.size(); }

/// Return the HeaderFileInfo structure for the specified FileEntry,
/// in preparation for updating it in some way.
/// Return the HeaderFileInfo structure for the specified FileEntry, in
/// preparation for updating it in some way.
HeaderFileInfo &getFileInfo(FileEntryRef FE);

/// Return the HeaderFileInfo structure for the specified FileEntry,
/// if it has ever been filled in.
/// \param WantExternal Whether the caller wants purely-external header file
/// info (where \p External is true).
const HeaderFileInfo *getExistingFileInfo(FileEntryRef FE,
bool WantExternal = true) const;
/// Return the HeaderFileInfo structure for the specified FileEntry, if it has
/// ever been filled in (either locally or externally).
const HeaderFileInfo *getExistingFileInfo(FileEntryRef FE) const;

/// Return the headerFileInfo structure for the specified FileEntry, if it has
/// ever been filled in locally.
const HeaderFileInfo *getExistingLocalFileInfo(FileEntryRef FE) const;

SearchDirIterator search_dir_begin() { return {*this, 0}; }
SearchDirIterator search_dir_end() { return {*this, SearchDirs.size()}; }
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/Lex/MacroInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ class ModuleMacro : public llvm::FoldingSetNode {
friend class Preprocessor;

/// The name defined by the macro.
IdentifierInfo *II;
const IdentifierInfo *II;

/// The body of the #define, or nullptr if this is a #undef.
MacroInfo *Macro;
Expand All @@ -529,7 +529,7 @@ class ModuleMacro : public llvm::FoldingSetNode {
/// The number of modules whose macros are directly overridden by this one.
unsigned NumOverrides;

ModuleMacro(Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro,
ModuleMacro(Module *OwningModule, const IdentifierInfo *II, MacroInfo *Macro,
ArrayRef<ModuleMacro *> Overrides)
: II(II), Macro(Macro), OwningModule(OwningModule),
NumOverrides(Overrides.size()) {
Expand All @@ -539,7 +539,7 @@ class ModuleMacro : public llvm::FoldingSetNode {

public:
static ModuleMacro *create(Preprocessor &PP, Module *OwningModule,
IdentifierInfo *II, MacroInfo *Macro,
const IdentifierInfo *II, MacroInfo *Macro,
ArrayRef<ModuleMacro *> Overrides);

void Profile(llvm::FoldingSetNodeID &ID) const {
Expand All @@ -553,7 +553,7 @@ class ModuleMacro : public llvm::FoldingSetNode {
}

/// Get the name of the macro.
IdentifierInfo *getName() const { return II; }
const IdentifierInfo *getName() const { return II; }

/// Get the ID of the module that exports this macro.
Module *getOwningModule() const { return OwningModule; }
Expand Down
9 changes: 5 additions & 4 deletions clang/include/clang/Lex/Preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ class Preprocessor {
ModuleMacroInfo *getModuleInfo(Preprocessor &PP,
const IdentifierInfo *II) const {
if (II->isOutOfDate())
PP.updateOutOfDateIdentifier(const_cast<IdentifierInfo&>(*II));
PP.updateOutOfDateIdentifier(*II);
// FIXME: Find a spare bit on IdentifierInfo and store a
// HasModuleMacros flag.
if (!II->hasMacroDefinition() ||
Expand Down Expand Up @@ -1162,7 +1162,7 @@ class Preprocessor {
/// skipped.
llvm::DenseMap<const char *, unsigned> RecordedSkippedRanges;

void updateOutOfDateIdentifier(IdentifierInfo &II) const;
void updateOutOfDateIdentifier(const IdentifierInfo &II) const;

public:
Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
Expand Down Expand Up @@ -1432,14 +1432,15 @@ class Preprocessor {
MacroDirective *MD);

/// Register an exported macro for a module and identifier.
ModuleMacro *addModuleMacro(Module *Mod, IdentifierInfo *II, MacroInfo *Macro,
ModuleMacro *addModuleMacro(Module *Mod, const IdentifierInfo *II,
MacroInfo *Macro,
ArrayRef<ModuleMacro *> Overrides, bool &IsNew);
ModuleMacro *getModuleMacro(Module *Mod, const IdentifierInfo *II);

/// Get the list of leaf (non-overridden) module macros for a name.
ArrayRef<ModuleMacro*> getLeafModuleMacros(const IdentifierInfo *II) const {
if (II->isOutOfDate())
updateOutOfDateIdentifier(const_cast<IdentifierInfo&>(*II));
updateOutOfDateIdentifier(*II);
auto I = LeafModuleMacros.find(II);
if (I != LeafModuleMacros.end())
return I->second;
Expand Down
21 changes: 11 additions & 10 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ class Parser : public CodeCompletionHandler {
};

/// Identifiers which have been declared within a tentative parse.
SmallVector<IdentifierInfo *, 8> TentativelyDeclaredIdentifiers;
SmallVector<const IdentifierInfo *, 8> TentativelyDeclaredIdentifiers;

/// Tracker for '<' tokens that might have been intended to be treated as an
/// angle bracket instead of a less-than comparison.
Expand Down Expand Up @@ -1927,15 +1927,11 @@ class Parser : public CodeCompletionHandler {
bool EnteringContext, IdentifierInfo &II,
CXXScopeSpec &SS);

bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
ParsedType ObjectType,
bool ObjectHasErrors,
bool EnteringContext,
bool *MayBePseudoDestructor = nullptr,
bool IsTypename = false,
IdentifierInfo **LastII = nullptr,
bool OnlyNamespace = false,
bool InUsingDeclaration = false);
bool ParseOptionalCXXScopeSpecifier(
CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHasErrors,
bool EnteringContext, bool *MayBePseudoDestructor = nullptr,
bool IsTypename = false, const IdentifierInfo **LastII = nullptr,
bool OnlyNamespace = false, bool InUsingDeclaration = false);

//===--------------------------------------------------------------------===//
// C++11 5.1.2: Lambda expressions
Expand Down Expand Up @@ -3615,6 +3611,9 @@ class Parser : public CodeCompletionHandler {
OpenACCClauseParseResult OpenACCCannotContinue();
OpenACCClauseParseResult OpenACCSuccess(OpenACCClause *Clause);

using OpenACCConditionExprParseResult =
std::pair<ExprResult, OpenACCParseCanContinue>;

/// Parses the OpenACC directive (the entire pragma) including the clause
/// list, but does not produce the main AST node.
OpenACCDirectiveParseInfo ParseOpenACCDirective();
Expand Down Expand Up @@ -3661,6 +3660,8 @@ class Parser : public CodeCompletionHandler {
bool ParseOpenACCGangArgList();
/// Parses a 'gang-arg', used for the 'gang' clause.
bool ParseOpenACCGangArg();
/// Parses a 'condition' expr, ensuring it results in a
ExprResult ParseOpenACCConditionExpr();

private:
//===--------------------------------------------------------------------===//
Expand Down
9 changes: 5 additions & 4 deletions clang/include/clang/Sema/CodeCompleteConsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ class CodeCompletionContext {
QualType BaseType;

/// The identifiers for Objective-C selector parts.
ArrayRef<IdentifierInfo *> SelIdents;
ArrayRef<const IdentifierInfo *> SelIdents;

/// The scope specifier that comes before the completion token e.g.
/// "a::b::"
Expand All @@ -378,8 +378,9 @@ class CodeCompletionContext {
: CCKind(CCKind), IsUsingDeclaration(false), SelIdents(std::nullopt) {}

/// Construct a new code-completion context of the given kind.
CodeCompletionContext(Kind CCKind, QualType T,
ArrayRef<IdentifierInfo *> SelIdents = std::nullopt)
CodeCompletionContext(
Kind CCKind, QualType T,
ArrayRef<const IdentifierInfo *> SelIdents = std::nullopt)
: CCKind(CCKind), IsUsingDeclaration(false), SelIdents(SelIdents) {
if (CCKind == CCC_DotMemberAccess || CCKind == CCC_ArrowMemberAccess ||
CCKind == CCC_ObjCPropertyAccess || CCKind == CCC_ObjCClassMessage ||
Expand All @@ -406,7 +407,7 @@ class CodeCompletionContext {
QualType getBaseType() const { return BaseType; }

/// Retrieve the Objective-C selector identifiers.
ArrayRef<IdentifierInfo *> getSelIdents() const { return SelIdents; }
ArrayRef<const IdentifierInfo *> getSelIdents() const { return SelIdents; }

/// Determines whether we want C++ constructors as results within this
/// context.
Expand Down
23 changes: 11 additions & 12 deletions clang/include/clang/Sema/DeclSpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ class UnqualifiedId {
union {
/// When Kind == IK_Identifier, the parsed identifier, or when
/// Kind == IK_UserLiteralId, the identifier suffix.
IdentifierInfo *Identifier;
const IdentifierInfo *Identifier;

/// When Kind == IK_OperatorFunctionId, the overloaded operator
/// that we parsed.
Expand Down Expand Up @@ -1111,7 +1111,7 @@ class UnqualifiedId {
/// \param IdLoc the location of the parsed identifier.
void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) {
Kind = UnqualifiedIdKind::IK_Identifier;
Identifier = const_cast<IdentifierInfo *>(Id);
Identifier = Id;
StartLocation = EndLocation = IdLoc;
}

Expand Down Expand Up @@ -1154,9 +1154,9 @@ class UnqualifiedId {
///
/// \param IdLoc the location of the identifier.
void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc,
SourceLocation IdLoc) {
SourceLocation IdLoc) {
Kind = UnqualifiedIdKind::IK_LiteralOperatorId;
Identifier = const_cast<IdentifierInfo *>(Id);
Identifier = Id;
StartLocation = OpLoc;
EndLocation = IdLoc;
}
Expand Down Expand Up @@ -1225,7 +1225,7 @@ class UnqualifiedId {
/// \param Id the identifier.
void setImplicitSelfParam(const IdentifierInfo *Id) {
Kind = UnqualifiedIdKind::IK_ImplicitSelfParam;
Identifier = const_cast<IdentifierInfo *>(Id);
Identifier = Id;
StartLocation = EndLocation = SourceLocation();
}

Expand Down Expand Up @@ -1327,7 +1327,7 @@ struct DeclaratorChunk {
/// Parameter type lists will have type info (if the actions module provides
/// it), but may have null identifier info: e.g. for 'void foo(int X, int)'.
struct ParamInfo {
IdentifierInfo *Ident;
const IdentifierInfo *Ident;
SourceLocation IdentLoc;
Decl *Param;

Expand All @@ -1339,11 +1339,10 @@ struct DeclaratorChunk {
std::unique_ptr<CachedTokens> DefaultArgTokens;

ParamInfo() = default;
ParamInfo(IdentifierInfo *ident, SourceLocation iloc,
Decl *param,
ParamInfo(const IdentifierInfo *ident, SourceLocation iloc, Decl *param,
std::unique_ptr<CachedTokens> DefArgTokens = nullptr)
: Ident(ident), IdentLoc(iloc), Param(param),
DefaultArgTokens(std::move(DefArgTokens)) {}
: Ident(ident), IdentLoc(iloc), Param(param),
DefaultArgTokens(std::move(DefArgTokens)) {}
};

struct TypeAndRange {
Expand Down Expand Up @@ -2326,7 +2325,7 @@ class Declarator {
return BindingGroup.isSet();
}

IdentifierInfo *getIdentifier() const {
const IdentifierInfo *getIdentifier() const {
if (Name.getKind() == UnqualifiedIdKind::IK_Identifier)
return Name.Identifier;

Expand All @@ -2335,7 +2334,7 @@ class Declarator {
SourceLocation getIdentifierLoc() const { return Name.StartLocation; }

/// Set the name of this declarator to be the given identifier.
void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) {
Name.setIdentifier(Id, IdLoc);
}

Expand Down
7 changes: 4 additions & 3 deletions clang/include/clang/Sema/ParsedTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ namespace clang {
SourceLocation TemplateNameLoc;

/// FIXME: Temporarily stores the name of a specialization
IdentifierInfo *Name;
const IdentifierInfo *Name;

/// FIXME: Temporarily stores the overloaded operator kind.
OverloadedOperatorKind Operator;
Expand Down Expand Up @@ -197,7 +197,7 @@ namespace clang {
/// appends it to List.
static TemplateIdAnnotation *
Create(SourceLocation TemplateKWLoc, SourceLocation TemplateNameLoc,
IdentifierInfo *Name, OverloadedOperatorKind OperatorKind,
const IdentifierInfo *Name, OverloadedOperatorKind OperatorKind,
ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind,
SourceLocation LAngleLoc, SourceLocation RAngleLoc,
ArrayRef<ParsedTemplateArgument> TemplateArgs, bool ArgsInvalid,
Expand Down Expand Up @@ -236,7 +236,8 @@ namespace clang {
TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;

TemplateIdAnnotation(SourceLocation TemplateKWLoc,
SourceLocation TemplateNameLoc, IdentifierInfo *Name,
SourceLocation TemplateNameLoc,
const IdentifierInfo *Name,
OverloadedOperatorKind OperatorKind,
ParsedTemplateTy OpaqueTemplateName,
TemplateNameKind TemplateKind,
Expand Down
215 changes: 111 additions & 104 deletions clang/include/clang/Sema/Sema.h

Large diffs are not rendered by default.

27 changes: 23 additions & 4 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,42 @@
#ifndef LLVM_CLANG_SEMA_SEMAHLSL_H
#define LLVM_CLANG_SEMA_SEMAHLSL_H

#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaBase.h"
#include <initializer_list>

namespace clang {

class SemaHLSL : public SemaBase {
public:
SemaHLSL(Sema &S);

Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
SourceLocation KwLoc, IdentifierInfo *Ident,
SourceLocation IdentLoc, SourceLocation LBrace);
void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace);
Decl *ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc,
IdentifierInfo *Ident, SourceLocation IdentLoc,
SourceLocation LBrace);
void ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace);
HLSLNumThreadsAttr *mergeNumThreadsAttr(Decl *D,
const AttributeCommonInfo &AL, int X,
int Y, int Z);
HLSLShaderAttr *mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL,
HLSLShaderAttr::ShaderType ShaderType);
HLSLParamModifierAttr *
mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL,
HLSLParamModifierAttr::Spelling Spelling);
void ActOnTopLevelFunction(FunctionDecl *FD);
void CheckEntryPoint(FunctionDecl *FD);
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
const HLSLAnnotationAttr *AnnotationAttr);
void DiagnoseAttrStageMismatch(
const Attr *A, HLSLShaderAttr::ShaderType Stage,
std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages);
};

} // namespace clang
Expand Down
28 changes: 27 additions & 1 deletion clang/include/clang/Sema/SemaOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ class SemaOpenACC : public SemaBase {
OpenACCDefaultClauseKind DefaultClauseKind;
};

std::variant<DefaultDetails> Details;
struct ConditionDetails {
Expr *ConditionExpr;
};

std::variant<DefaultDetails, ConditionDetails> Details;

public:
OpenACCParsedClause(OpenACCDirectiveKind DirKind,
Expand All @@ -63,6 +67,16 @@ class SemaOpenACC : public SemaBase {
return std::get<DefaultDetails>(Details).DefaultClauseKind;
}

const Expr *getConditionExpr() const {
return const_cast<OpenACCParsedClause *>(this)->getConditionExpr();
}

Expr *getConditionExpr() {
assert(ClauseKind == OpenACCClauseKind::If &&
"Parsed clause kind does not have a condition expr");
return std::get<ConditionDetails>(Details).ConditionExpr;
}

void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }

Expand All @@ -71,6 +85,18 @@ class SemaOpenACC : public SemaBase {
"Parsed clause is not a default clause");
Details = DefaultDetails{DefKind};
}

void setConditionDetails(Expr *ConditionExpr) {
assert(ClauseKind == OpenACCClauseKind::If &&
"Parsed clause kind does not have a condition expr");
// In C++ we can count on this being a 'bool', but in C this gets left as
// some sort of scalar that codegen will have to take care of converting.
assert((!ConditionExpr || ConditionExpr->isInstantiationDependent() ||
ConditionExpr->getType()->isScalarType()) &&
"Condition expression type not scalar/dependent");

Details = ConditionDetails{ConditionExpr};
}
};

SemaOpenACC(Sema &S);
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,10 @@ enum ASTRecordTypes {
/// Record code for an unterminated \#pragma clang assume_nonnull begin
/// recorded in a preamble.
PP_ASSUME_NONNULL_LOC = 67,

/// Record code for lexical and visible block for delayed namespace in
/// reduced BMI.
DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD = 68,
};

/// Record types used within a source manager block.
Expand Down
25 changes: 20 additions & 5 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,20 @@ class ASTReader
/// in the chain.
DeclUpdateOffsetsMap DeclUpdateOffsets;

using DelayedNamespaceOffsetMapTy = llvm::DenseMap<
serialization::DeclID,
std::pair</*LexicalOffset*/ uint64_t, /*VisibleOffset*/ uint64_t>>;

/// Mapping from global declaration IDs to the lexical and visible block
/// offset for delayed namespace in reduced BMI.
///
/// We can't use the existing DeclUpdate mechanism since the DeclUpdate
/// may only be applied in an outer most read. However, we need to know
/// whether or not a DeclContext has external storage during the recursive
/// reading. So we need to apply the offset immediately after we read the
/// namespace as if it is not delayed.
DelayedNamespaceOffsetMapTy DelayedNamespaceOffsetMap;

struct PendingUpdateRecord {
Decl *D;
serialization::GlobalDeclID ID;
Expand Down Expand Up @@ -1082,12 +1096,12 @@ class ASTReader

/// The set of lookup results that we have faked in order to support
/// merging of partially deserialized decls but that we have not yet removed.
llvm::SmallMapVector<IdentifierInfo *, SmallVector<NamedDecl*, 2>, 16>
PendingFakeLookupResults;
llvm::SmallMapVector<const IdentifierInfo *, SmallVector<NamedDecl *, 2>, 16>
PendingFakeLookupResults;

/// The generation number of each identifier, which keeps track of
/// the last time we loaded information about this identifier.
llvm::DenseMap<IdentifierInfo *, unsigned> IdentifierGeneration;
llvm::DenseMap<const IdentifierInfo *, unsigned> IdentifierGeneration;

/// Contains declarations and definitions that could be
/// "interesting" to the ASTConsumer, when we get that AST consumer.
Expand Down Expand Up @@ -1492,6 +1506,7 @@ class ASTReader
getModuleFileLevelDecls(ModuleFile &Mod);

private:
bool isConsumerInterestedIn(Decl *D);
void PassInterestingDeclsToConsumer();
void PassInterestingDeclToConsumer(Decl *D);

Expand Down Expand Up @@ -2330,10 +2345,10 @@ class ASTReader
void ReadDefinedMacros() override;

/// Update an out-of-date identifier.
void updateOutOfDateIdentifier(IdentifierInfo &II) override;
void updateOutOfDateIdentifier(const IdentifierInfo &II) override;

/// Note that this identifier is up-to-date.
void markIdentifierUpToDate(IdentifierInfo *II);
void markIdentifierUpToDate(const IdentifierInfo *II);

/// Load all external visible decls in the given DeclContext.
void completeVisibleDeclsMap(const DeclContext *DC) override;
Expand Down
26 changes: 25 additions & 1 deletion clang/include/clang/Serialization/ASTWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,16 @@ class ASTWriter : public ASTDeserializationListener,
/// The declarations and types to emit.
std::queue<DeclOrType> DeclTypesToEmit;

/// The delayed namespace to emit. Only meaningful for reduced BMI.
///
/// In reduced BMI, we want to elide the unreachable declarations in
/// the global module fragment. However, in ASTWriterDecl, when we see
/// a namespace, all the declarations in the namespace would be emitted.
/// So the optimization become meaningless. To solve the issue, we
/// delay recording all the declarations until we emit all the declarations.
/// Then we can safely record the reached declarations only.
llvm::SmallVector<NamespaceDecl *, 16> DelayedNamespace;

/// The first ID number we can use for our own declarations.
serialization::DeclID FirstDeclID = serialization::NUM_PREDEF_DECL_IDS;

Expand Down Expand Up @@ -529,7 +539,8 @@ class ASTWriter : public ASTDeserializationListener,
void WriteType(QualType T);

bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC);
bool isLookupResultEntirelyExternal(StoredDeclsList &Result, DeclContext *DC);
bool isLookupResultEntirelyExternalOrUnreachable(StoredDeclsList &Result,
DeclContext *DC);

void GenerateNameLookupTable(const DeclContext *DC,
llvm::SmallVectorImpl<char> &LookupTable);
Expand Down Expand Up @@ -704,6 +715,15 @@ class ASTWriter : public ASTDeserializationListener,
/// declaration.
serialization::DeclID getDeclID(const Decl *D);

/// Whether or not the declaration got emitted. If not, it wouldn't be
/// emitted.
///
/// This may only be called after we've done the job to write the
/// declarations (marked by DoneWritingDeclsAndTypes).
///
/// A declaration may only be omitted in reduced BMI.
bool wasDeclEmitted(const Decl *D) const;

unsigned getAnonymousDeclarationNumber(const NamedDecl *D);

/// Add a string to the given record.
Expand Down Expand Up @@ -798,6 +818,10 @@ class ASTWriter : public ASTDeserializationListener,
return WritingModule && WritingModule->isNamedModule();
}

bool isGeneratingReducedBMI() const { return GeneratingReducedBMI; }

bool getDoneWritingDeclsAndTypes() const { return DoneWritingDeclsAndTypes; }

private:
// ASTDeserializationListener implementation
void ReaderInitialized(ASTReader *Reader) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ class CachedFileSystemEntry {
CachedFileContents *Contents;
};

using CachedRealPath = llvm::ErrorOr<std::string>;

/// This class is a shared cache, that caches the 'stat' and 'open' calls to the
/// underlying real file system, and the scanned preprocessor directives of
/// files.
Expand All @@ -154,9 +156,11 @@ class DependencyScanningFilesystemSharedCache {
/// The mutex that needs to be locked before mutation of any member.
mutable std::mutex CacheLock;

/// Map from filenames to cached entries.
llvm::StringMap<const CachedFileSystemEntry *, llvm::BumpPtrAllocator>
EntriesByFilename;
/// Map from filenames to cached entries and real paths.
llvm::StringMap<
std::pair<const CachedFileSystemEntry *, const CachedRealPath *>,
llvm::BumpPtrAllocator>
CacheByFilename;

/// Map from unique IDs to cached entries.
llvm::DenseMap<llvm::sys::fs::UniqueID, const CachedFileSystemEntry *>
Expand All @@ -168,6 +172,9 @@ class DependencyScanningFilesystemSharedCache {
/// The backing storage for cached contents.
llvm::SpecificBumpPtrAllocator<CachedFileContents> ContentsStorage;

/// The backing storage for cached real paths.
llvm::SpecificBumpPtrAllocator<CachedRealPath> RealPathStorage;

/// Returns entry associated with the filename or nullptr if none is found.
const CachedFileSystemEntry *findEntryByFilename(StringRef Filename) const;

Expand All @@ -194,6 +201,17 @@ class DependencyScanningFilesystemSharedCache {
const CachedFileSystemEntry &
getOrInsertEntryForFilename(StringRef Filename,
const CachedFileSystemEntry &Entry);

/// Returns the real path associated with the filename or nullptr if none is
/// found.
const CachedRealPath *findRealPathByFilename(StringRef Filename) const;

/// Returns the real path associated with the filename if there is some.
/// Otherwise, constructs new one with the given one, associates it with the
/// filename and returns the result.
const CachedRealPath &
getOrEmplaceRealPathForFilename(StringRef Filename,
llvm::ErrorOr<StringRef> RealPath);
};

DependencyScanningFilesystemSharedCache();
Expand All @@ -210,14 +228,17 @@ class DependencyScanningFilesystemSharedCache {
/// This class is a local cache, that caches the 'stat' and 'open' calls to the
/// underlying real file system.
class DependencyScanningFilesystemLocalCache {
llvm::StringMap<const CachedFileSystemEntry *, llvm::BumpPtrAllocator> Cache;
llvm::StringMap<
std::pair<const CachedFileSystemEntry *, const CachedRealPath *>,
llvm::BumpPtrAllocator>
Cache;

public:
/// Returns entry associated with the filename or nullptr if none is found.
const CachedFileSystemEntry *findEntryByFilename(StringRef Filename) const {
assert(llvm::sys::path::is_absolute_gnu(Filename));
auto It = Cache.find(Filename);
return It == Cache.end() ? nullptr : It->getValue();
return It == Cache.end() ? nullptr : It->getValue().first;
}

/// Associates the given entry with the filename and returns the given entry
Expand All @@ -226,9 +247,40 @@ class DependencyScanningFilesystemLocalCache {
insertEntryForFilename(StringRef Filename,
const CachedFileSystemEntry &Entry) {
assert(llvm::sys::path::is_absolute_gnu(Filename));
const auto *InsertedEntry = Cache.insert({Filename, &Entry}).first->second;
assert(InsertedEntry == &Entry && "entry already present");
return *InsertedEntry;
auto [It, Inserted] = Cache.insert({Filename, {&Entry, nullptr}});
auto &[CachedEntry, CachedRealPath] = It->getValue();
if (!Inserted) {
// The file is already present in the local cache. If we got here, it only
// contains the real path. Let's make sure the entry is populated too.
assert((!CachedEntry && CachedRealPath) && "entry already present");
CachedEntry = &Entry;
}
return *CachedEntry;
}

/// Returns real path associated with the filename or nullptr if none is
/// found.
const CachedRealPath *findRealPathByFilename(StringRef Filename) const {
assert(llvm::sys::path::is_absolute_gnu(Filename));
auto It = Cache.find(Filename);
return It == Cache.end() ? nullptr : It->getValue().second;
}

/// Associates the given real path with the filename and returns the given
/// entry pointer (for convenience).
const CachedRealPath &
insertRealPathForFilename(StringRef Filename,
const CachedRealPath &RealPath) {
assert(llvm::sys::path::is_absolute_gnu(Filename));
auto [It, Inserted] = Cache.insert({Filename, {nullptr, &RealPath}});
auto &[CachedEntry, CachedRealPath] = It->getValue();
if (!Inserted) {
// The file is already present in the local cache. If we got here, it only
// contains the entry. Let's make sure the real path is populated too.
assert((!CachedRealPath && CachedEntry) && "real path already present");
CachedRealPath = &RealPath;
}
return *CachedRealPath;
}
};

Expand Down Expand Up @@ -296,6 +348,9 @@ class DependencyScanningWorkerFilesystem
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
openFileForRead(const Twine &Path) override;

std::error_code getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) override;

std::error_code setCurrentWorkingDirectory(const Twine &Path) override;

/// Returns entry for the given filename.
Expand Down Expand Up @@ -402,6 +457,10 @@ class DependencyScanningWorkerFilesystem
llvm::ErrorOr<std::string> WorkingDirForCacheLookup;

void updateWorkingDirForCacheLookup();

llvm::ErrorOr<StringRef>
tryGetFilenameForLookup(StringRef OriginalFilename,
llvm::SmallVectorImpl<char> &PathBuf) const;
};

} // end namespace dependencies
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/ARCMigrate/ObjCMT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@ static bool IsValidIdentifier(ASTContext &Ctx,
return false;
std::string NameString = Name;
NameString[0] = toLowercase(NameString[0]);
IdentifierInfo *II = &Ctx.Idents.get(NameString);
const IdentifierInfo *II = &Ctx.Idents.get(NameString);
return II->getTokenID() == tok::identifier;
}

Expand All @@ -1166,7 +1166,7 @@ bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,
if (OIT_Family != OIT_None)
return false;

IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
const IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
Selector SetterSelector =
SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
PP.getSelectorTable(),
Expand Down Expand Up @@ -1311,7 +1311,8 @@ void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
std::string StringLoweredClassName = LoweredClassName.lower();
LoweredClassName = StringLoweredClassName;

IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0);
const IdentifierInfo *MethodIdName =
OM->getSelector().getIdentifierInfoForSlot(0);
// Handle method with no name at its first selector slot; e.g. + (id):(int)x.
if (!MethodIdName)
return;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/ARCMigrate/TransAPIUses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class APIChecker : public RecursiveASTVisitor<APIChecker> {
getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));
setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));

IdentifierInfo *selIds[2];
const IdentifierInfo *selIds[2];
selIds[0] = &ids.get("getArgument");
selIds[1] = &ids.get("atIndex");
getArgumentSel = sels.getSelector(2, selIds);
Expand Down
13 changes: 5 additions & 8 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(

TemplateTemplateParmDecl *CanonTTP = TemplateTemplateParmDecl::Create(
*this, getTranslationUnitDecl(), SourceLocation(), TTP->getDepth(),
TTP->getPosition(), TTP->isParameterPack(), nullptr,
TTP->getPosition(), TTP->isParameterPack(), nullptr, /*Typename=*/false,
TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(),
CanonParams, SourceLocation(),
/*RequiresClause=*/nullptr));
Expand Down Expand Up @@ -6929,16 +6929,13 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
// typedef typename T::type T1;
// typedef typename T1::type T2;
if (const auto *DNT = T->getAs<DependentNameType>())
return NestedNameSpecifier::Create(
*this, DNT->getQualifier(),
const_cast<IdentifierInfo *>(DNT->getIdentifier()));
return NestedNameSpecifier::Create(*this, DNT->getQualifier(),
DNT->getIdentifier());
if (const auto *DTST = T->getAs<DependentTemplateSpecializationType>())
return NestedNameSpecifier::Create(*this, DTST->getQualifier(), true,
const_cast<Type *>(T));
return NestedNameSpecifier::Create(*this, DTST->getQualifier(), true, T);

// TODO: Set 'Template' parameter to true for other template types.
return NestedNameSpecifier::Create(*this, nullptr, false,
const_cast<Type *>(T));
return NestedNameSpecifier::Create(*this, nullptr, false, T);
}

case NestedNameSpecifier::Global:
Expand Down
9 changes: 5 additions & 4 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5952,7 +5952,8 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
ToD, D, Importer.getToContext(),
Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr,
D->getDepth(), D->getPosition(), D->isParameterPack(),
(*NameOrErr).getAsIdentifierInfo(), *TemplateParamsOrErr))
(*NameOrErr).getAsIdentifierInfo(), D->wasDeclaredWithTypename(),
*TemplateParamsOrErr))
return ToD;

if (D->hasDefaultArgument()) {
Expand Down Expand Up @@ -8383,8 +8384,8 @@ ASTNodeImporter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
return std::move(Err);

PseudoDestructorTypeStorage Storage;
if (IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) {
IdentifierInfo *ToII = Importer.Import(FromII);
if (const IdentifierInfo *FromII = E->getDestroyedTypeIdentifier()) {
const IdentifierInfo *ToII = Importer.Import(FromII);
ExpectedSLoc ToDestroyedTypeLocOrErr = import(E->getDestroyedTypeLoc());
if (!ToDestroyedTypeLocOrErr)
return ToDestroyedTypeLocOrErr.takeError();
Expand Down Expand Up @@ -10194,7 +10195,7 @@ Expected<Selector> ASTImporter::Import(Selector FromSel) {
if (FromSel.isNull())
return Selector{};

SmallVector<IdentifierInfo *, 4> Idents;
SmallVector<const IdentifierInfo *, 4> Idents;
Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(0)));
for (unsigned I = 1, N = FromSel.getNumArgs(); I < N; ++I)
Idents.push_back(Import(FromSel.getIdentifierInfoForSlot(I)));
Expand Down
18 changes: 10 additions & 8 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2913,10 +2913,10 @@ VarDecl::setInstantiationOfStaticDataMember(VarDecl *VD,
//===----------------------------------------------------------------------===//

ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo,
StorageClass S, Expr *DefArg) {
SourceLocation StartLoc, SourceLocation IdLoc,
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, StorageClass S,
Expr *DefArg) {
return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo,
S, DefArg);
}
Expand Down Expand Up @@ -4511,7 +4511,7 @@ unsigned FunctionDecl::getODRHash() {

FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, QualType T,
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
InClassInitStyle InitStyle) {
return new (C, DC) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo,
Expand Down Expand Up @@ -5438,7 +5438,7 @@ IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC,

IndirectFieldDecl *
IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
const IdentifierInfo *Id, QualType T,
llvm::MutableArrayRef<NamedDecl *> CH) {
return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH);
}
Expand All @@ -5461,7 +5461,8 @@ void TypeDecl::anchor() {}

TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, TypeSourceInfo *TInfo) {
const IdentifierInfo *Id,
TypeSourceInfo *TInfo) {
return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
}

Expand Down Expand Up @@ -5511,7 +5512,8 @@ TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) {

TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
SourceLocation IdLoc,
const IdentifierInfo *Id,
TypeSourceInfo *TInfo) {
return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
}
Expand Down
94 changes: 38 additions & 56 deletions clang/lib/AST/DeclObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts,
//===----------------------------------------------------------------------===//

ObjCContainerDecl::ObjCContainerDecl(Kind DK, DeclContext *DC,
IdentifierInfo *Id, SourceLocation nameLoc,
const IdentifierInfo *Id,
SourceLocation nameLoc,
SourceLocation atStartLoc)
: NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK) {
setAtStartLoc(atStartLoc);
Expand Down Expand Up @@ -378,10 +379,8 @@ SourceLocation ObjCInterfaceDecl::getSuperClassLoc() const {
/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
/// with name 'PropertyId' in the primary class; including those in protocols
/// (direct or indirect) used by the primary class.
ObjCPropertyDecl *
ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
IdentifierInfo *PropertyId,
ObjCPropertyQueryKind QueryKind) const {
ObjCPropertyDecl *ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
const IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return nullptr;
Expand Down Expand Up @@ -1539,14 +1538,10 @@ void ObjCTypeParamList::gatherDefaultTypeArgs(
// ObjCInterfaceDecl
//===----------------------------------------------------------------------===//

ObjCInterfaceDecl *ObjCInterfaceDecl::Create(const ASTContext &C,
DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
ObjCTypeParamList *typeParamList,
ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc,
bool isInternal){
ObjCInterfaceDecl *ObjCInterfaceDecl::Create(
const ASTContext &C, DeclContext *DC, SourceLocation atLoc,
const IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
ObjCInterfaceDecl *PrevDecl, SourceLocation ClassLoc, bool isInternal) {
auto *Result = new (C, DC)
ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl,
isInternal);
Expand All @@ -1564,12 +1559,10 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
return Result;
}

ObjCInterfaceDecl::ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC,
SourceLocation AtLoc, IdentifierInfo *Id,
ObjCTypeParamList *typeParamList,
SourceLocation CLoc,
ObjCInterfaceDecl *PrevDecl,
bool IsInternal)
ObjCInterfaceDecl::ObjCInterfaceDecl(
const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
const IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl, bool IsInternal)
: ObjCContainerDecl(ObjCInterface, DC, Id, CLoc, AtLoc),
redeclarable_base(C) {
setPreviousDecl(PrevDecl);
Expand Down Expand Up @@ -1751,8 +1744,8 @@ ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() {
/// categories for this class and returns it. Name of the category is passed
/// in 'CategoryId'. If category not found, return 0;
///
ObjCCategoryDecl *
ObjCInterfaceDecl::FindCategoryDeclaration(IdentifierInfo *CategoryId) const {
ObjCCategoryDecl *ObjCInterfaceDecl::FindCategoryDeclaration(
const IdentifierInfo *CategoryId) const {
// FIXME: Should make sure no callers ever do this.
if (!hasDefinition())
return nullptr;
Expand Down Expand Up @@ -1838,10 +1831,10 @@ void ObjCIvarDecl::anchor() {}

ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo,
AccessControl ac, Expr *BW,
bool synthesized) {
SourceLocation IdLoc,
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, AccessControl ac,
Expr *BW, bool synthesized) {
if (DC) {
// Ivar's can only appear in interfaces, implementations (via synthesized
// properties), and class extensions (via direct declaration, or synthesized
Expand Down Expand Up @@ -2120,28 +2113,23 @@ void ObjCProtocolDecl::setHasODRHash(bool HasHash) {

void ObjCCategoryDecl::anchor() {}

ObjCCategoryDecl::ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc,
SourceLocation IvarRBraceLoc)
ObjCCategoryDecl::ObjCCategoryDecl(
DeclContext *DC, SourceLocation AtLoc, SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc, const IdentifierInfo *Id,
ObjCInterfaceDecl *IDecl, ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc, SourceLocation IvarRBraceLoc)
: ObjCContainerDecl(ObjCCategory, DC, Id, ClassNameLoc, AtLoc),
ClassInterface(IDecl), CategoryNameLoc(CategoryNameLoc),
IvarLBraceLoc(IvarLBraceLoc), IvarRBraceLoc(IvarRBraceLoc) {
setTypeParamList(typeParamList);
}

ObjCCategoryDecl *ObjCCategoryDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id,
ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc,
SourceLocation IvarRBraceLoc) {
ObjCCategoryDecl *ObjCCategoryDecl::Create(
ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
const IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList, SourceLocation IvarLBraceLoc,
SourceLocation IvarRBraceLoc) {
auto *CatDecl =
new (C, DC) ObjCCategoryDecl(DC, AtLoc, ClassNameLoc, CategoryNameLoc, Id,
IDecl, typeParamList, IvarLBraceLoc,
Expand Down Expand Up @@ -2190,13 +2178,10 @@ void ObjCCategoryDecl::setTypeParamList(ObjCTypeParamList *TPL) {

void ObjCCategoryImplDecl::anchor() {}

ObjCCategoryImplDecl *
ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
ObjCInterfaceDecl *ClassInterface,
SourceLocation nameLoc,
SourceLocation atStartLoc,
SourceLocation CategoryNameLoc) {
ObjCCategoryImplDecl *ObjCCategoryImplDecl::Create(
ASTContext &C, DeclContext *DC, const IdentifierInfo *Id,
ObjCInterfaceDecl *ClassInterface, SourceLocation nameLoc,
SourceLocation atStartLoc, SourceLocation CategoryNameLoc) {
if (ClassInterface && ClassInterface->hasDefinition())
ClassInterface = ClassInterface->getDefinition();
return new (C, DC) ObjCCategoryImplDecl(DC, Id, ClassInterface, nameLoc,
Expand Down Expand Up @@ -2365,14 +2350,11 @@ ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) {

void ObjCPropertyDecl::anchor() {}

ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
IdentifierInfo *Id,
SourceLocation AtLoc,
SourceLocation LParenLoc,
QualType T,
TypeSourceInfo *TSI,
PropertyControl propControl) {
ObjCPropertyDecl *
ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
const IdentifierInfo *Id, SourceLocation AtLoc,
SourceLocation LParenLoc, QualType T,
TypeSourceInfo *TSI, PropertyControl propControl) {
return new (C, DC) ObjCPropertyDecl(DC, L, Id, AtLoc, LParenLoc, T, TSI,
propControl);
}
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/AST/DeclPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,10 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {

if (const TemplateTemplateParmDecl *TTP =
dyn_cast<TemplateTemplateParmDecl>(D)) {
Out << "class";
if (TTP->wasDeclaredWithTypename())
Out << "typename";
else
Out << "class";

if (TTP->isParameterPack())
Out << " ...";
Expand Down
32 changes: 15 additions & 17 deletions clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ void TemplateTypeParmDecl::setTypeConstraint(

NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(
DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
unsigned P, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
ArrayRef<QualType> ExpandedTypes, ArrayRef<TypeSourceInfo *> ExpandedTInfos)
: DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
TemplateParmPosition(D, P), ParameterPack(true),
Expand All @@ -730,12 +730,10 @@ NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(
}
}

NonTypeTemplateParmDecl *
NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
unsigned D, unsigned P, IdentifierInfo *Id,
QualType T, bool ParameterPack,
TypeSourceInfo *TInfo) {
NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
QualType T, bool ParameterPack, TypeSourceInfo *TInfo) {
AutoType *AT =
C.getLangOpts().CPlusPlus20 ? T->getContainedAutoType() : nullptr;
return new (C, DC,
Expand All @@ -748,7 +746,7 @@ NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,

NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
ArrayRef<TypeSourceInfo *> ExpandedTInfos) {
AutoType *AT = TInfo->getType()->getContainedAutoType();
Expand Down Expand Up @@ -807,10 +805,10 @@ void TemplateTemplateParmDecl::anchor() {}

TemplateTemplateParmDecl::TemplateTemplateParmDecl(
DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id, TemplateParameterList *Params,
IdentifierInfo *Id, bool Typename, TemplateParameterList *Params,
ArrayRef<TemplateParameterList *> Expansions)
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
TemplateParmPosition(D, P), ParameterPack(true),
TemplateParmPosition(D, P), Typename(Typename), ParameterPack(true),
ExpandedParameterPack(true), NumExpandedParams(Expansions.size()) {
if (!Expansions.empty())
std::uninitialized_copy(Expansions.begin(), Expansions.end(),
Expand All @@ -821,26 +819,26 @@ TemplateTemplateParmDecl *
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
bool ParameterPack, IdentifierInfo *Id,
TemplateParameterList *Params) {
bool Typename, TemplateParameterList *Params) {
return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
Params);
Typename, Params);
}

TemplateTemplateParmDecl *
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id,
IdentifierInfo *Id, bool Typename,
TemplateParameterList *Params,
ArrayRef<TemplateParameterList *> Expansions) {
return new (C, DC,
additionalSizeToAlloc<TemplateParameterList *>(Expansions.size()))
TemplateTemplateParmDecl(DC, L, D, P, Id, Params, Expansions);
TemplateTemplateParmDecl(DC, L, D, P, Id, Typename, Params, Expansions);
}

TemplateTemplateParmDecl *
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0,
false, nullptr, nullptr);
false, nullptr, false, nullptr);
}

TemplateTemplateParmDecl *
Expand All @@ -849,7 +847,7 @@ TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
auto *TTP =
new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions))
TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
nullptr, std::nullopt);
false, nullptr, std::nullopt);
TTP->NumExpandedParams = NumExpansions;
return TTP;
}
Expand Down Expand Up @@ -1471,7 +1469,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
// template <typename T, ...Ints> class IntSeq
auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
/*ParameterPack=*/false, /*Id=*/nullptr, TPL);
/*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, TPL);
TemplateTemplateParm->setImplicit(true);

// typename T
Expand Down
34 changes: 21 additions & 13 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2778,26 +2778,34 @@ bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
std::optional<PrimType> VarT = classify(VD->getType());

if (Context::shouldBeGloballyIndexed(VD)) {
// We've already seen and initialized this global.
if (P.getGlobal(VD))
return true;

std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);

if (!GlobalIndex)
return false;

if (Init) {
auto initGlobal = [&](unsigned GlobalIndex) -> bool {
assert(Init);
DeclScope<Emitter> LocalScope(this, VD);

if (VarT) {
if (!this->visit(Init))
return false;
return this->emitInitGlobal(*VarT, *GlobalIndex, VD);
return this->emitInitGlobal(*VarT, GlobalIndex, VD);
}
return this->visitGlobalInitializer(Init, *GlobalIndex);
return this->visitGlobalInitializer(Init, GlobalIndex);
};

// We've already seen and initialized this global.
if (std::optional<unsigned> GlobalIndex = P.getGlobal(VD)) {
if (P.getPtrGlobal(*GlobalIndex).isInitialized())
return true;

// The previous attempt at initialization might've been unsuccessful,
// so let's try this one.
return Init && initGlobal(*GlobalIndex);
}
return true;

std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);

if (!GlobalIndex)
return false;

return !Init || initGlobal(*GlobalIndex);
} else {
VariableScope<Emitter> LocalScope(this);
if (VarT) {
Expand Down
26 changes: 20 additions & 6 deletions clang/lib/AST/Interp/FunctionPointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,45 @@ namespace interp {
class FunctionPointer final {
private:
const Function *Func;
bool Valid;

public:
// FIXME: We might want to track the fact that the Function pointer
// has been created from an integer and is most likely garbage anyway.
FunctionPointer(uintptr_t IntVal = 0, const Descriptor *Desc = nullptr)
: Func(reinterpret_cast<const Function *>(IntVal)) {}
FunctionPointer(const Function *Func) : Func(Func), Valid(true) {
assert(Func);
}

FunctionPointer(const Function *Func) : Func(Func) { assert(Func); }
FunctionPointer(uintptr_t IntVal = 0, const Descriptor *Desc = nullptr)
: Func(reinterpret_cast<const Function *>(IntVal)), Valid(false) {}

const Function *getFunction() const { return Func; }
bool isZero() const { return !Func; }
bool isWeak() const {
if (!Func || !Valid)
return false;

return Func->getDecl()->isWeak();
}

APValue toAPValue() const {
if (!Func)
return APValue(static_cast<Expr *>(nullptr), CharUnits::Zero(), {},
/*OnePastTheEnd=*/false, /*IsNull=*/true);

if (!Valid)
return APValue(static_cast<Expr *>(nullptr),
CharUnits::fromQuantity(getIntegerRepresentation()), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);

return APValue(Func->getDecl(), CharUnits::Zero(), {},
/*OnePastTheEnd=*/false, /*IsNull=*/false);
}

void print(llvm::raw_ostream &OS) const {
OS << "FnPtr(";
if (Func)
if (Func && Valid)
OS << Func->getName();
else if (Func)
OS << reinterpret_cast<uintptr_t>(Func);
else
OS << "nullptr";
OS << ")";
Expand Down
99 changes: 62 additions & 37 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,65 @@ static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
return true;
}

static void diagnoseMissingInitializer(InterpState &S, CodePtr OpPC,
const ValueDecl *VD) {
const SourceInfo &E = S.Current->getSource(OpPC);
S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
}

static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
const ValueDecl *VD);
static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
const ValueDecl *D) {
const SourceInfo &E = S.Current->getSource(OpPC);

if (isa<ParmVarDecl>(D)) {
if (S.getLangOpts().CPlusPlus11) {
S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
} else {
S.FFDiag(E);
}
} else if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (!VD->getType().isConstQualified()) {
diagnoseNonConstVariable(S, OpPC, VD);
return false;
}

// const, but no initializer.
if (!VD->getAnyInitializer()) {
diagnoseMissingInitializer(S, OpPC, VD);
return false;
}
}
return false;
}

static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
const ValueDecl *VD) {
if (!S.getLangOpts().CPlusPlus)
return;

const SourceInfo &Loc = S.Current->getSource(OpPC);
if (const auto *VarD = dyn_cast<VarDecl>(VD);
VarD && VarD->getType().isConstQualified() &&
!VarD->getAnyInitializer()) {
diagnoseMissingInitializer(S, OpPC, VD);
return;
}

if (VD->getType()->isIntegralOrEnumerationType())
if (VD->getType()->isIntegralOrEnumerationType()) {
S.FFDiag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD;
else
S.FFDiag(Loc,
S.getLangOpts().CPlusPlus11
? diag::note_constexpr_ltor_non_constexpr
: diag::note_constexpr_ltor_non_integral,
1)
<< VD << VD->getType();
S.Note(VD->getLocation(), diag::note_declared_at);
return;
}

S.FFDiag(Loc,
S.getLangOpts().CPlusPlus11 ? diag::note_constexpr_ltor_non_constexpr
: diag::note_constexpr_ltor_non_integral,
1)
<< VD << VD->getType();
S.Note(VD->getLocation(), diag::note_declared_at);
}

Expand Down Expand Up @@ -202,6 +245,9 @@ bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!Ptr.isExtern())
return true;

if (Ptr.isInitialized())
return true;

if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
const auto *VD = Ptr.getDeclDesc()->asValueDecl();
diagnoseNonConstVariable(S, OpPC, VD);
Expand Down Expand Up @@ -369,9 +415,15 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
VD && VD->hasGlobalStorage()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
S.Note(VD->getLocation(), diag::note_declared_at);
if (VD->getAnyInitializer()) {
S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
S.Note(VD->getLocation(), diag::note_declared_at);
} else {
diagnoseMissingInitializer(S, OpPC, VD);
}
return false;
}

if (!S.checkingPotentialConstantExpression()) {
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
<< AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
Expand Down Expand Up @@ -598,33 +650,6 @@ bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
return true;
}

static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
const ValueDecl *D) {
const SourceInfo &E = S.Current->getSource(OpPC);

if (isa<ParmVarDecl>(D)) {
if (S.getLangOpts().CPlusPlus11) {
S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D;
S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange();
} else {
S.FFDiag(E);
}
} else if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (!VD->getType().isConstQualified()) {
diagnoseNonConstVariable(S, OpPC, VD);
return false;
}

// const, but no initializer.
if (!VD->getAnyInitializer()) {
S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD;
S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange();
return false;
}
}
return false;
}

/// We aleady know the given DeclRefExpr is invalid for some reason,
/// now figure out why and print appropriate diagnostics.
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ inline bool CmpHelperEQ<FunctionPointer>(InterpState &S, CodePtr OpPC,

// We cannot compare against weak declarations at compile time.
for (const auto &FP : {LHS, RHS}) {
if (!FP.isZero() && FP.getFunction()->getDecl()->isWeak()) {
if (FP.isWeak()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
<< FP.toDiagnosticString(S.getCtx());
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/AST/Interp/InterpState.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ class InterpState final : public State, public SourceMapper {

/// Delegates source mapping to the mapper.
SourceInfo getSource(const Function *F, CodePtr PC) const override {
return M ? M->getSource(F, PC) : F->getSource(PC);
if (M)
return M->getSource(F, PC);

assert(F && "Function cannot be null");
return F->getSource(PC);
}

Context &getContext() const { return Ctx; }
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
bool IsStatic, IsExtern;
if (const auto *Var = dyn_cast<VarDecl>(VD)) {
IsStatic = Context::shouldBeGloballyIndexed(VD);
IsExtern = !Var->getAnyInitializer();
IsExtern = Var->hasExternalStorage();
} else if (isa<UnnamedGlobalConstantDecl, MSGuidDecl>(VD)) {
IsStatic = true;
IsExtern = false;
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/JSONNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1576,6 +1576,14 @@ void JSONNodeDumper::VisitMaterializeTemporaryExpr(
attributeOnlyIfTrue("boundToLValueRef", MTE->isBoundToLvalueReference());
}

void JSONNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit());
}

void JSONNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit());
}

void JSONNodeDumper::VisitCXXDependentScopeMemberExpr(
const CXXDependentScopeMemberExpr *DSME) {
JOS.attribute("isArrow", DSME->isArrow());
Expand Down
104 changes: 37 additions & 67 deletions clang/lib/AST/NSAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,8 @@ Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
&Ctx.Idents.get("initWithUTF8String"));
break;
case NSStr_stringWithCStringEncoding: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("stringWithCString"),
&Ctx.Idents.get("encoding")
};
const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("stringWithCString"),
&Ctx.Idents.get("encoding")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
Expand Down Expand Up @@ -93,10 +91,8 @@ Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
break;
case NSArr_arrayWithObjectsCount: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("arrayWithObjects"),
&Ctx.Idents.get("count")
};
const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("arrayWithObjects"),
&Ctx.Idents.get("count")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
Expand All @@ -110,29 +106,24 @@ Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
break;
case NSMutableArr_replaceObjectAtIndex: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("replaceObjectAtIndex"),
&Ctx.Idents.get("withObject")
};
const IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("replaceObjectAtIndex"),
&Ctx.Idents.get("withObject")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
case NSMutableArr_addObject:
Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
break;
case NSMutableArr_insertObjectAtIndex: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("insertObject"),
&Ctx.Idents.get("atIndex")
};
const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("insertObject"),
&Ctx.Idents.get("atIndex")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
case NSMutableArr_setObjectAtIndexedSubscript: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("setObject"),
&Ctx.Idents.get("atIndexedSubscript")
};
const IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("setObject"), &Ctx.Idents.get("atIndexedSubscript")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
Expand Down Expand Up @@ -167,27 +158,21 @@ Selector NSAPI::getNSDictionarySelector(
&Ctx.Idents.get("dictionaryWithDictionary"));
break;
case NSDict_dictionaryWithObjectForKey: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("dictionaryWithObject"),
&Ctx.Idents.get("forKey")
};
const IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("dictionaryWithObject"), &Ctx.Idents.get("forKey")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
case NSDict_dictionaryWithObjectsForKeys: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("dictionaryWithObjects"),
&Ctx.Idents.get("forKeys")
};
const IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("dictionaryWithObjects"), &Ctx.Idents.get("forKeys")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
case NSDict_dictionaryWithObjectsForKeysCount: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("dictionaryWithObjects"),
&Ctx.Idents.get("forKeys"),
&Ctx.Idents.get("count")
};
const IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("dictionaryWithObjects"), &Ctx.Idents.get("forKeys"),
&Ctx.Idents.get("count")};
Sel = Ctx.Selectors.getSelector(3, KeyIdents);
break;
}
Expand All @@ -204,37 +189,29 @@ Selector NSAPI::getNSDictionarySelector(
&Ctx.Idents.get("initWithObjectsAndKeys"));
break;
case NSDict_initWithObjectsForKeys: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("initWithObjects"),
&Ctx.Idents.get("forKeys")
};
const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("initWithObjects"),
&Ctx.Idents.get("forKeys")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
case NSDict_objectForKey:
Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
break;
case NSMutableDict_setObjectForKey: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("setObject"),
&Ctx.Idents.get("forKey")
};
const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("setObject"),
&Ctx.Idents.get("forKey")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
case NSMutableDict_setObjectForKeyedSubscript: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("setObject"),
&Ctx.Idents.get("forKeyedSubscript")
};
const IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("setObject"), &Ctx.Idents.get("forKeyedSubscript")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
case NSMutableDict_setValueForKey: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("setValue"),
&Ctx.Idents.get("forKey")
};
const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("setValue"),
&Ctx.Idents.get("forKey")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
Expand Down Expand Up @@ -264,34 +241,27 @@ Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
break;
case NSOrderedSet_insertObjectAtIndex: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("insertObject"),
&Ctx.Idents.get("atIndex")
};
const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("insertObject"),
&Ctx.Idents.get("atIndex")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
case NSOrderedSet_setObjectAtIndex: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("setObject"),
&Ctx.Idents.get("atIndex")
};
const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get("setObject"),
&Ctx.Idents.get("atIndex")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
case NSOrderedSet_setObjectAtIndexedSubscript: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("setObject"),
&Ctx.Idents.get("atIndexedSubscript")
};
const IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("setObject"), &Ctx.Idents.get("atIndexedSubscript")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
case NSOrderedSet_replaceObjectAtIndexWithObject: {
IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("replaceObjectAtIndex"),
&Ctx.Idents.get("withObject")
};
const IdentifierInfo *KeyIdents[] = {
&Ctx.Idents.get("replaceObjectAtIndex"),
&Ctx.Idents.get("withObject")};
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
break;
}
Expand Down Expand Up @@ -606,7 +576,7 @@ bool NSAPI::isObjCEnumerator(const Expr *E,
Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
Selector &Sel) const {
if (Sel.isNull()) {
SmallVector<IdentifierInfo *, 4> Idents;
SmallVector<const IdentifierInfo *, 4> Idents;
for (ArrayRef<StringRef>::const_iterator
I = Ids.begin(), E = Ids.end(); I != E; ++I)
Idents.push_back(&Ctx.Idents.get(*I));
Expand All @@ -617,7 +587,7 @@ Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,

Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
if (Sel.isNull()) {
IdentifierInfo *Ident = &Ctx.Idents.get(Id);
const IdentifierInfo *Ident = &Ctx.Idents.get(Id);
Sel = Ctx.Selectors.getSelector(0, &Ident);
}
return Sel;
Expand Down
18 changes: 9 additions & 9 deletions clang/lib/AST/NestedNameSpecifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,16 @@ NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
return NNS;
}

NestedNameSpecifier *
NestedNameSpecifier::Create(const ASTContext &Context,
NestedNameSpecifier *Prefix, IdentifierInfo *II) {
NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
const IdentifierInfo *II) {
assert(II && "Identifier cannot be NULL");
assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");

NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
Mockup.Prefix.setInt(StoredIdentifier);
Mockup.Specifier = II;
Mockup.Specifier = const_cast<IdentifierInfo *>(II);
return FindOrInsert(Context, Mockup);
}

Expand All @@ -87,7 +87,7 @@ NestedNameSpecifier::Create(const ASTContext &Context,
NestedNameSpecifier *
NestedNameSpecifier::Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
NamespaceAliasDecl *Alias) {
const NamespaceAliasDecl *Alias) {
assert(Alias && "Namespace alias cannot be NULL");
assert((!Prefix ||
(Prefix->getAsType() == nullptr &&
Expand All @@ -96,7 +96,7 @@ NestedNameSpecifier::Create(const ASTContext &Context,
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(Prefix);
Mockup.Prefix.setInt(StoredDecl);
Mockup.Specifier = Alias;
Mockup.Specifier = const_cast<NamespaceAliasDecl *>(Alias);
return FindOrInsert(Context, Mockup);
}

Expand All @@ -112,13 +112,13 @@ NestedNameSpecifier::Create(const ASTContext &Context,
return FindOrInsert(Context, Mockup);
}

NestedNameSpecifier *
NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
const IdentifierInfo *II) {
assert(II && "Identifier cannot be NULL");
NestedNameSpecifier Mockup;
Mockup.Prefix.setPointer(nullptr);
Mockup.Prefix.setInt(StoredIdentifier);
Mockup.Specifier = II;
Mockup.Specifier = const_cast<IdentifierInfo *>(II);
return FindOrInsert(Context, Mockup);
}

Expand Down
39 changes: 39 additions & 0 deletions clang/lib/AST/OpenACCClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "clang/AST/OpenACCClause.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"

using namespace clang;

Expand All @@ -27,10 +28,48 @@ OpenACCDefaultClause *OpenACCDefaultClause::Create(const ASTContext &C,
return new (Mem) OpenACCDefaultClause(K, BeginLoc, LParenLoc, EndLoc);
}

OpenACCIfClause *OpenACCIfClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
Expr *ConditionExpr,
SourceLocation EndLoc) {
void *Mem = C.Allocate(sizeof(OpenACCIfClause), alignof(OpenACCIfClause));
return new (Mem) OpenACCIfClause(BeginLoc, LParenLoc, ConditionExpr, EndLoc);
}

OpenACCIfClause::OpenACCIfClause(SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *ConditionExpr,
SourceLocation EndLoc)
: OpenACCClauseWithCondition(OpenACCClauseKind::If, BeginLoc, LParenLoc,
ConditionExpr, EndLoc) {
assert(ConditionExpr && "if clause requires condition expr");
assert((ConditionExpr->isInstantiationDependent() ||
ConditionExpr->getType()->isScalarType()) &&
"Condition expression type not scalar/dependent");
}

OpenACCClause::child_range OpenACCClause::children() {
switch (getClauseKind()) {
default:
assert(false && "Clause children function not implemented");
break;
#define VISIT_CLAUSE(CLAUSE_NAME) \
case OpenACCClauseKind::CLAUSE_NAME: \
return cast<OpenACC##CLAUSE_NAME##Clause>(this)->children();

#include "clang/Basic/OpenACCClauses.def"
}
return child_range(child_iterator(), child_iterator());
}

//===----------------------------------------------------------------------===//
// OpenACC clauses printing methods
//===----------------------------------------------------------------------===//
void OpenACCClausePrinter::VisitOpenACCDefaultClause(
const OpenACCDefaultClause &C) {
OS << "default(" << C.getDefaultClauseKind() << ")";
}

void OpenACCClausePrinter::VisitOpenACCIfClause(const OpenACCIfClause &C) {
OS << "if(" << C.getConditionExpr() << ")";
}
4 changes: 2 additions & 2 deletions clang/lib/AST/SelectorLocationsKind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ static SourceLocation getStandardSelLoc(unsigned Index,
assert(Index == 0);
if (EndLoc.isInvalid())
return SourceLocation();
IdentifierInfo *II = Sel.getIdentifierInfoForSlot(0);
const IdentifierInfo *II = Sel.getIdentifierInfoForSlot(0);
unsigned Len = II ? II->getLength() : 0;
return EndLoc.getLocWithOffset(-Len);
}

assert(Index < NumSelArgs);
if (ArgLoc.isInvalid())
return SourceLocation();
IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Index);
const IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Index);
unsigned Len = /* selector id */ (II ? II->getLength() : 0) + /* ':' */ 1;
if (WithArgSpace)
++Len;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1447,7 +1447,7 @@ void StmtPrinter::VisitOffsetOfExpr(OffsetOfExpr *Node) {
continue;

// Field or identifier node.
IdentifierInfo *Id = ON.getFieldName();
const IdentifierInfo *Id = ON.getFieldName();
if (!Id)
continue;

Expand Down Expand Up @@ -2348,7 +2348,7 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
E->getQualifier()->print(OS, Policy);
OS << "~";

if (IdentifierInfo *II = E->getDestroyedTypeIdentifier())
if (const IdentifierInfo *II = E->getDestroyedTypeIdentifier())
OS << II->getName();
else
E->getDestroyedType().print(OS, Policy);
Expand Down
25 changes: 19 additions & 6 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ namespace {
virtual void VisitName(DeclarationName Name, bool TreatAsDecl = false) = 0;

/// Visit identifiers that are not in Decl's or Type's.
virtual void VisitIdentifierInfo(IdentifierInfo *II) = 0;
virtual void VisitIdentifierInfo(const IdentifierInfo *II) = 0;

/// Visit a nested-name-specifier that occurs within an expression
/// or statement.
Expand Down Expand Up @@ -163,7 +163,7 @@ namespace {
ID.AddPointer(Name.getAsOpaquePtr());
}

void VisitIdentifierInfo(IdentifierInfo *II) override {
void VisitIdentifierInfo(const IdentifierInfo *II) override {
ID.AddPointer(II);
}

Expand Down Expand Up @@ -211,7 +211,7 @@ namespace {
}
Hash.AddDeclarationName(Name, TreatAsDecl);
}
void VisitIdentifierInfo(IdentifierInfo *II) override {
void VisitIdentifierInfo(const IdentifierInfo *II) override {
ID.AddBoolean(II);
if (II) {
Hash.AddIdentifierInfo(II);
Expand Down Expand Up @@ -2445,9 +2445,10 @@ void StmtProfiler::VisitTemplateArgument(const TemplateArgument &Arg) {
namespace {
class OpenACCClauseProfiler
: public OpenACCClauseVisitor<OpenACCClauseProfiler> {
StmtProfiler &Profiler;

public:
OpenACCClauseProfiler() = default;
OpenACCClauseProfiler(StmtProfiler &P) : Profiler(P) {}

void VisitOpenACCClauseList(ArrayRef<const OpenACCClause *> Clauses) {
for (const OpenACCClause *Clause : Clauses) {
Expand All @@ -2456,20 +2457,32 @@ class OpenACCClauseProfiler
Visit(Clause);
}
}
void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause);

#define VISIT_CLAUSE(CLAUSE_NAME) \
void VisitOpenACC##CLAUSE_NAME##Clause( \
const OpenACC##CLAUSE_NAME##Clause &Clause);

#include "clang/Basic/OpenACCClauses.def"
};

/// Nothing to do here, there are no sub-statements.
void OpenACCClauseProfiler::VisitOpenACCDefaultClause(
const OpenACCDefaultClause &Clause) {}

void OpenACCClauseProfiler::VisitOpenACCIfClause(
const OpenACCIfClause &Clause) {
assert(Clause.hasConditionExpr() &&
"if clause requires a valid condition expr");
Profiler.VisitStmt(Clause.getConditionExpr());
}
} // namespace

void StmtProfiler::VisitOpenACCComputeConstruct(
const OpenACCComputeConstruct *S) {
// VisitStmt handles children, so the AssociatedStmt is handled.
VisitStmt(S);

OpenACCClauseProfiler P;
OpenACCClauseProfiler P{*this};
P.VisitOpenACCClauseList(S->clauses());
}

Expand Down
19 changes: 7 additions & 12 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,11 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
case OpenACCClauseKind::Default:
OS << '(' << cast<OpenACCDefaultClause>(C)->getDefaultClauseKind() << ')';
break;
case OpenACCClauseKind::If:
// The condition expression will be printed as a part of the 'children',
// but print 'clause' here so it is clear what is happening from the dump.
OS << " clause";
break;
default:
// Nothing to do here.
break;
Expand Down Expand Up @@ -1450,23 +1455,13 @@ void TextNodeDumper::VisitExpressionTraitExpr(const ExpressionTraitExpr *Node) {
}

void TextNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
if (Node->hasRewrittenInit()) {
if (Node->hasRewrittenInit())
OS << " has rewritten init";
AddChild([=] {
ColorScope Color(OS, ShowColors, StmtColor);
Visit(Node->getExpr());
});
}
}

void TextNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
if (Node->hasRewrittenInit()) {
if (Node->hasRewrittenInit())
OS << " has rewritten init";
AddChild([=] {
ColorScope Color(OS, ShowColors, StmtColor);
Visit(Node->getExpr());
});
}
}

void TextNodeDumper::VisitMaterializeTemporaryExpr(
Expand Down
427 changes: 307 additions & 120 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Large diffs are not rendered by default.

176 changes: 78 additions & 98 deletions clang/lib/Analysis/FlowSensitive/Transfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,25 +460,41 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
// So make sure we have a value if we didn't propagate one above.
if (S->isPRValue() && S->getType()->isRecordType()) {
if (Env.getValue(*S) == nullptr) {
Value *Val = Env.createValue(S->getType());
// We're guaranteed to always be able to create a value for record
// types.
assert(Val != nullptr);
Env.setValue(*S, *Val);
auto &Loc = Env.getResultObjectLocation(*S);
Env.initializeFieldsWithValues(Loc);
refreshRecordValue(Loc, Env);
}
}
}

void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
const Expr *InitExpr = S->getExpr();
assert(InitExpr != nullptr);

// If this is a prvalue of record type, the handler for `*InitExpr` (if one
// exists) will initialize the result object; there is no value to propgate
// here.
if (S->getType()->isRecordType() && S->isPRValue())
return;

propagateValueOrStorageLocation(*InitExpr, *S, Env);
}

void VisitCXXConstructExpr(const CXXConstructExpr *S) {
const CXXConstructorDecl *ConstructorDecl = S->getConstructor();
assert(ConstructorDecl != nullptr);

// `CXXConstructExpr` can have array type if default-initializing an array
// of records. We don't handle this specifically beyond potentially inlining
// the call.
if (!S->getType()->isRecordType()) {
transferInlineCall(S, ConstructorDecl);
return;
}

RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.setValue(*S, refreshRecordValue(Loc, Env));

if (ConstructorDecl->isCopyOrMoveConstructor()) {
// It is permissible for a copy/move constructor to have additional
// parameters as long as they have default arguments defined for them.
Expand All @@ -491,24 +507,14 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
if (ArgLoc == nullptr)
return;

if (S->isElidable()) {
if (Value *Val = Env.getValue(*ArgLoc))
Env.setValue(*S, *Val);
} else {
auto &Val = *cast<RecordValue>(Env.createValue(S->getType()));
Env.setValue(*S, Val);
copyRecord(*ArgLoc, Val.getLoc(), Env);
}
// Even if the copy/move constructor call is elidable, we choose to copy
// the record in all cases (which isn't wrong, just potentially not
// optimal).
copyRecord(*ArgLoc, Loc, Env);
return;
}

// `CXXConstructExpr` can have array type if default-initializing an array
// of records, and we currently can't create values for arrays. So check if
// we've got a record type.
if (S->getType()->isRecordType()) {
auto &InitialVal = *cast<RecordValue>(Env.createValue(S->getType()));
Env.setValue(*S, InitialVal);
}
Env.initializeFieldsWithValues(Loc, S->getType());

transferInlineCall(S, ConstructorDecl);
}
Expand Down Expand Up @@ -551,19 +557,15 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
if (S->isGLValue()) {
Env.setStorageLocation(*S, *LocDst);
} else if (S->getType()->isRecordType()) {
// Make sure that we have a `RecordValue` for this expression so that
// `Environment::getResultObjectLocation()` is able to return a location
// for it.
if (Env.getValue(*S) == nullptr)
refreshRecordValue(*S, Env);
// Assume that the assignment returns the assigned value.
copyRecord(*LocDst, Env.getResultObjectLocation(*S), Env);
}

return;
}

// CXXOperatorCallExpr can be prvalues. Call `VisitCallExpr`() to create
// a `RecordValue` for them so that `Environment::getResultObjectLocation()`
// can return a value.
// `CXXOperatorCallExpr` can be a prvalue. Call `VisitCallExpr`() to
// initialize the prvalue's fields with values.
VisitCallExpr(S);
}

Expand All @@ -580,11 +582,6 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
}
}

void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) {
if (Value *Val = Env.createValue(S->getType()))
Env.setValue(*S, *Val);
}

void VisitCallExpr(const CallExpr *S) {
// Of clang's builtins, only `__builtin_expect` is handled explicitly, since
// others (like trap, debugtrap, and unreachable) are handled by CFG
Expand Down Expand Up @@ -612,13 +609,14 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
} else if (const FunctionDecl *F = S->getDirectCallee()) {
transferInlineCall(S, F);

// If this call produces a prvalue of record type, make sure that we have
// a `RecordValue` for it. This is required so that
// `Environment::getResultObjectLocation()` is able to return a location
// for this `CallExpr`.
// If this call produces a prvalue of record type, initialize its fields
// with values.
if (S->getType()->isRecordType() && S->isPRValue())
if (Env.getValue(*S) == nullptr)
refreshRecordValue(*S, Env);
if (Env.getValue(*S) == nullptr) {
RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.initializeFieldsWithValues(Loc);
Env.setValue(*S, refreshRecordValue(Loc, Env));
}
}
}

Expand Down Expand Up @@ -666,8 +664,10 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
// `getLogicOperatorSubExprValue()`.
if (S->isGLValue())
Env.setStorageLocation(*S, Env.createObject(S->getType()));
else if (Value *Val = Env.createValue(S->getType()))
Env.setValue(*S, *Val);
else if (!S->getType()->isRecordType()) {
if (Value *Val = Env.createValue(S->getType()))
Env.setValue(*S, *Val);
}
}

void VisitInitListExpr(const InitListExpr *S) {
Expand All @@ -688,71 +688,51 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> {
return;
}

llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
RecordInitListHelper InitListHelper(S);
RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
Env.setValue(*S, refreshRecordValue(Loc, Env));

for (auto [Base, Init] : InitListHelper.base_inits()) {
assert(Base->getType().getCanonicalType() ==
Init->getType().getCanonicalType());
auto *BaseVal = Env.get<RecordValue>(*Init);
if (!BaseVal)
BaseVal = cast<RecordValue>(Env.createValue(Init->getType()));
// Take ownership of the fields of the `RecordValue` for the base class
// and incorporate them into the "flattened" set of fields for the
// derived class.
auto Children = BaseVal->getLoc().children();
FieldLocs.insert(Children.begin(), Children.end());
}
// Initialization of base classes and fields of record type happens when we
// visit the nested `CXXConstructExpr` or `InitListExpr` for that base class
// or field. We therefore only need to deal with fields of non-record type
// here.

for (auto [Field, Init] : InitListHelper.field_inits()) {
assert(
// The types are same, or
Field->getType().getCanonicalType().getUnqualifiedType() ==
Init->getType().getCanonicalType().getUnqualifiedType() ||
// The field's type is T&, and initializer is T
(Field->getType()->isReferenceType() &&
Field->getType().getCanonicalType()->getPointeeType() ==
Init->getType().getCanonicalType()));
auto& Loc = Env.createObject(Field->getType(), Init);
FieldLocs.insert({Field, &Loc});
}
RecordInitListHelper InitListHelper(S);

// In the case of a union, we don't in general have initializers for all
// of the fields. Create storage locations for the remaining fields (but
// don't associate them with values).
if (Type->isUnionType()) {
for (const FieldDecl *Field :
Env.getDataflowAnalysisContext().getModeledFields(Type)) {
if (auto [it, inserted] = FieldLocs.insert({Field, nullptr}); inserted)
it->second = &Env.createStorageLocation(Field->getType());
for (auto [Field, Init] : InitListHelper.field_inits()) {
if (Field->getType()->isRecordType())
continue;
if (Field->getType()->isReferenceType()) {
assert(Field->getType().getCanonicalType()->getPointeeType() ==
Init->getType().getCanonicalType());
Loc.setChild(*Field, &Env.createObject(Field->getType(), Init));
continue;
}
assert(Field->getType().getCanonicalType().getUnqualifiedType() ==
Init->getType().getCanonicalType().getUnqualifiedType());
StorageLocation *FieldLoc = Loc.getChild(*Field);
// Locations for non-reference fields must always be non-null.
assert(FieldLoc != nullptr);
Value *Val = Env.getValue(*Init);
if (Val == nullptr && isa<ImplicitValueInitExpr>(Init) &&
Init->getType()->isPointerType())
Val =
&Env.getOrCreateNullPointerValue(Init->getType()->getPointeeType());
if (Val == nullptr)
Val = Env.createValue(Field->getType());
if (Val != nullptr)
Env.setValue(*FieldLoc, *Val);
}

// Check that we satisfy the invariant that a `RecordStorageLoation`
// contains exactly the set of modeled fields for that type.
// `ModeledFields` includes fields from all the bases, but only the
// modeled ones. However, if a class type is initialized with an
// `InitListExpr`, all fields in the class, including those from base
// classes, are included in the set of modeled fields. The code above
// should therefore populate exactly the modeled fields.
assert(containsSameFields(
Env.getDataflowAnalysisContext().getModeledFields(Type), FieldLocs));

RecordStorageLocation::SyntheticFieldMap SyntheticFieldLocs;
for (const auto &Entry :
Env.getDataflowAnalysisContext().getSyntheticFields(Type)) {
SyntheticFieldLocs.insert(
{Entry.getKey(), &Env.createObject(Entry.getValue())});
for (const auto &[FieldName, FieldLoc] : Loc.synthetic_fields()) {
QualType FieldType = FieldLoc->getType();
if (FieldType->isRecordType()) {
Env.initializeFieldsWithValues(*cast<RecordStorageLocation>(FieldLoc));
} else {
if (Value *Val = Env.createValue(FieldType))
Env.setValue(*FieldLoc, *Val);
}
}

auto &Loc = Env.getDataflowAnalysisContext().createRecordStorageLocation(
Type, std::move(FieldLocs), std::move(SyntheticFieldLocs));
RecordValue &RecordVal = Env.create<RecordValue>(Loc);

Env.setValue(Loc, RecordVal);

Env.setValue(*S, RecordVal);

// FIXME: Implement array initialization.
}

Expand Down
13 changes: 3 additions & 10 deletions clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,17 +369,10 @@ builtinTransferInitializer(const CFGInitializer &Elt,
ParentLoc->setChild(*Member, InitExprLoc);
} else if (auto *InitExprVal = Env.getValue(*InitExpr)) {
assert(MemberLoc != nullptr);
if (Member->getType()->isRecordType()) {
auto *InitValStruct = cast<RecordValue>(InitExprVal);
// FIXME: Rather than performing a copy here, we should really be
// initializing the field in place. This would require us to propagate the
// storage location of the field to the AST node that creates the
// `RecordValue`.
copyRecord(InitValStruct->getLoc(),
*cast<RecordStorageLocation>(MemberLoc), Env);
} else {
// Record-type initializers construct themselves directly into the result
// object, so there is no need to handle them here.
if (!Member->getType()->isRecordType())
Env.setValue(*MemberLoc, *InitExprVal);
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Analysis/ObjCNoReturn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

using namespace clang;

static bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) {
static bool isSubclass(const ObjCInterfaceDecl *Class,
const IdentifierInfo *II) {
if (!Class)
return false;
if (Class->getIdentifier() == II)
Expand All @@ -30,7 +31,7 @@ ObjCNoReturn::ObjCNoReturn(ASTContext &C)
NSExceptionII(&C.Idents.get("NSException"))
{
// Generate selectors.
SmallVector<IdentifierInfo*, 3> II;
SmallVector<const IdentifierInfo *, 3> II;

// raise:format:
II.push_back(&C.Idents.get("raise"));
Expand Down
16 changes: 9 additions & 7 deletions clang/lib/Basic/IdentifierTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,8 @@ unsigned Selector::getNumArgs() const {
return SI->getNumArgs();
}

IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
const IdentifierInfo *
Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
if (getIdentifierInfoFlag() < MultiArg) {
assert(argIndex == 0 && "illegal keyword index");
return getAsIdentifierInfo();
Expand All @@ -553,7 +554,7 @@ IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
}

StringRef Selector::getNameForSlot(unsigned int argIndex) const {
IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
const IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
return II ? II->getName() : StringRef();
}

Expand All @@ -574,7 +575,7 @@ std::string Selector::getAsString() const {
return "<null selector>";

if (getIdentifierInfoFlag() < MultiArg) {
IdentifierInfo *II = getAsIdentifierInfo();
const IdentifierInfo *II = getAsIdentifierInfo();

if (getNumArgs() == 0) {
assert(II && "If the number of arguments is 0 then II is guaranteed to "
Expand Down Expand Up @@ -608,7 +609,7 @@ static bool startsWithWord(StringRef name, StringRef word) {
}

ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
if (!first) return OMF_None;

StringRef name = first->getName();
Expand Down Expand Up @@ -655,7 +656,7 @@ ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
}

ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
if (!first) return OIT_None;

StringRef name = first->getName();
Expand Down Expand Up @@ -683,7 +684,7 @@ ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
}

ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
if (!first) return SFF_None;

StringRef name = first->getName();
Expand Down Expand Up @@ -750,7 +751,8 @@ size_t SelectorTable::getTotalMemory() const {
return SelTabImpl.Allocator.getTotalMemory();
}

Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
Selector SelectorTable::getSelector(unsigned nKeys,
const IdentifierInfo **IIV) {
if (nKeys < 2)
return Selector(IIV[0], nKeys);

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Basic/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,9 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__CCMP__");
if (HasCF)
Builder.defineMacro("__CF__");
// Condition here is aligned with the feature set of mapxf in Options.td
if (HasEGPR && HasPush2Pop2 && HasPPX && HasNDD)
Builder.defineMacro("__APX_F__");

// Each case falls through to the previous one here.
switch (SSELevel) {
Expand Down
Empty file added clang/lib/CIR/CMakeLists.txt
Empty file.
4 changes: 4 additions & 0 deletions clang/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ if(CLANG_INCLUDE_TESTS)
endif()
add_subdirectory(Interpreter)
add_subdirectory(Support)

if(CLANG_ENABLE_CIR)
add_subdirectory(CIR)
endif()
6 changes: 5 additions & 1 deletion clang/lib/CodeGen/CGAtomic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1806,7 +1806,11 @@ void AtomicInfo::EmitAtomicUpdateOp(
/*NumReservedValues=*/2);
PHI->addIncoming(OldVal, CurBB);
Address NewAtomicAddr = CreateTempAlloca();
Address NewAtomicIntAddr = castToAtomicIntPointer(NewAtomicAddr);
Address NewAtomicIntAddr =
shouldCastToInt(NewAtomicAddr.getElementType(), /*CmpXchg=*/true)
? castToAtomicIntPointer(NewAtomicAddr)
: NewAtomicAddr;

if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
requiresMemSetZero(getAtomicAddress().getElementType())) {
CGF.Builder.CreateStore(PHI, NewAtomicIntAddr);
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1447,7 +1447,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(
selfTy = getContext().getPointerType(getContext().getAddrSpaceQualType(
getContext().VoidTy, LangAS::opencl_generic));

IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
const IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");

ImplicitParamDecl SelfDecl(getContext(), const_cast<BlockDecl *>(blockDecl),
SourceLocation(), II, selfTy,
Expand Down Expand Up @@ -2791,7 +2791,7 @@ static void configureBlocksRuntimeObject(CodeGenModule &CGM,
auto *GV = cast<llvm::GlobalValue>(C->stripPointerCasts());

if (CGM.getTarget().getTriple().isOSBinFormatCOFF()) {
IdentifierInfo &II = CGM.getContext().Idents.get(C->getName());
const IdentifierInfo &II = CGM.getContext().Idents.get(C->getName());
TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);

Expand Down
13 changes: 10 additions & 3 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18312,9 +18312,16 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
Value *Op0 = EmitScalarExpr(E->getArg(0));
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
llvm_unreachable("rcp operand must have a float representation");
return Builder.CreateIntrinsic(
/*ReturnType=*/Op0->getType(), Intrinsic::dx_rcp,
ArrayRef<Value *>{Op0}, nullptr, "dx.rcp");
llvm::Type *Ty = Op0->getType();
llvm::Type *EltTy = Ty->getScalarType();
Constant *One =
Ty->isVectorTy()
? ConstantVector::getSplat(
ElementCount::getFixed(
dyn_cast<FixedVectorType>(Ty)->getNumElements()),
ConstantFP::get(EltTy, 1.0))
: ConstantFP::get(EltTy, 1.0);
return Builder.CreateFDiv(One, Op0, "hlsl.rcp");
}
case Builtin::BI__builtin_hlsl_elementwise_rsqrt: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGCUDANV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF,
KernelLaunchAPI = KernelLaunchAPI + "_ptsz";
}
auto LaunchKernelName = addPrefixToName(KernelLaunchAPI);
IdentifierInfo &cudaLaunchKernelII =
const IdentifierInfo &cudaLaunchKernelII =
CGM.getContext().Idents.get(LaunchKernelName);
FunctionDecl *cudaLaunchKernelFD = nullptr;
for (auto *Result : DC->lookup(&cudaLaunchKernelII)) {
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4124,7 +4124,8 @@ static bool isProvablyNull(llvm::Value *addr) {
}

static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) {
return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout());
return llvm::isKnownNonZero(Addr.getBasePointer(), /*Depth=*/0,
CGF.CGM.getDataLayout());
}

/// Emit the actual writing-back of a writeback.
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1384,7 +1384,7 @@ void CodeGenFunction::EmitAndRegisterVariableArrayDimensions(
// For each dimension stores its QualType and corresponding
// size-expression Value.
SmallVector<CodeGenFunction::VlaSizePair, 4> Dimensions;
SmallVector<IdentifierInfo *, 4> VLAExprNames;
SmallVector<const IdentifierInfo *, 4> VLAExprNames;

// Break down the array into individual dimensions.
QualType Type1D = D.getType();
Expand Down Expand Up @@ -1421,7 +1421,7 @@ void CodeGenFunction::EmitAndRegisterVariableArrayDimensions(
MD = llvm::ConstantAsMetadata::get(C);
else {
// Create an artificial VarDecl to generate debug info for.
IdentifierInfo *NameIdent = VLAExprNames[NameIdx++];
const IdentifierInfo *NameIdent = VLAExprNames[NameIdx++];
auto QT = getContext().getIntTypeForBitwidth(
SizeTy->getScalarSizeInBits(), false);
auto *ArtificialDecl = VarDecl::Create(
Expand Down
Loading