mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This fixes the following tests which are now crashing due to hitting unreachable "no buffer containing location found" in `SourceManager::findBufferContainingLoc`: - attr/attr_dynamic_member_lookup.swift - AutoDiff/Sema/DerivativeRegistrationCrossModule/main.swift - Constraints/construction.swift - Constraints/members.swift - NameLookup/accessibility.swift - Sema/call_as_function_simple.swift The root cause of the crash is as follows. All the tests involve emitting `InaccessibleMemberFailure` error diagnostic (see `InaccessibleMemberFailure::diagnoseAsError`). When `DeclNameLoc nameLoc` is initialized via default constructor and is not re-assigned with smth meaningful later, the check `nameLoc.isValid()` returns `true` even though it should be `false`. It turns out that we treat `const void *LocationInfo` as `SourceLoc` and hope that if `LocationInfo` is `nullptr`, casting this to `SourceLoc` would produce a "default" `SourceLoc` with `Pointer` member set to `nullptr`. But such a cast (see `getSourceLocs()` member of `DeclNameLoc`) is undefined behavior. So, the compiler assumes that `Pointer` member of `SourceLoc` we try to cast to is not `nullptr` (due to strict aliasing rule), which leads to `nameLoc.isValid()` being mistakenly computed as `true`. This patch resolves the issue by handling this special case separately.
163 lines
5.2 KiB
C++
163 lines
5.2 KiB
C++
//===--- DeclNameLoc.h - Declaration Name Location Info ---------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the DeclNameLoc class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_AST_DECL_NAME_LOC_H
|
|
#define SWIFT_AST_DECL_NAME_LOC_H
|
|
|
|
#include "swift/Basic/LLVM.h"
|
|
#include "swift/Basic/SourceLoc.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
class BridgedDeclNameLoc;
|
|
|
|
namespace swift {
|
|
|
|
class ASTContext;
|
|
|
|
/// Source location information for a declaration name (\c DeclName)
|
|
/// written in the source.
|
|
class DeclNameLoc {
|
|
friend class ::BridgedDeclNameLoc;
|
|
|
|
/// Source location information.
|
|
///
|
|
/// If \c NumArgumentLabels == 0 and \c !HasModuleSelectorLoc, this is the
|
|
/// SourceLoc for the base name. Otherwise, it points to an array of
|
|
/// SourceLocs, which contains:
|
|
/// * The base name location
|
|
/// * The module selector location
|
|
/// * The left parentheses location
|
|
/// * The right parentheses location
|
|
/// * The locations of each of the argument labels.
|
|
const void *LocationInfo;
|
|
|
|
/// The number of argument labels stored in the name.
|
|
uint32_t NumArgumentLabels;
|
|
bool HasModuleSelectorLoc;
|
|
|
|
enum {
|
|
BaseNameIndex = 0,
|
|
ModuleSelectorIndex = 1,
|
|
LParenIndex = 2,
|
|
RParenIndex = 3,
|
|
FirstArgumentLabelIndex = 4,
|
|
};
|
|
|
|
/// Retrieve a pointer to either the only source location that was
|
|
/// stored or to the array of source locations that was stored.
|
|
SourceLoc const * getSourceLocs() const {
|
|
if (NumArgumentLabels == 0 && !HasModuleSelectorLoc) {
|
|
if (LocationInfo == nullptr)
|
|
return nullptr;
|
|
return reinterpret_cast<SourceLoc const *>(&LocationInfo);
|
|
}
|
|
|
|
return reinterpret_cast<SourceLoc const *>(LocationInfo);
|
|
}
|
|
|
|
DeclNameLoc(const void *LocationInfo, unsigned NumArgumentLabels,
|
|
bool HasModuleSelectorLoc)
|
|
: LocationInfo(LocationInfo), NumArgumentLabels(NumArgumentLabels),
|
|
HasModuleSelectorLoc(HasModuleSelectorLoc) {}
|
|
|
|
public:
|
|
/// Create an invalid declaration name location.
|
|
DeclNameLoc() : DeclNameLoc(nullptr, 0, false) {}
|
|
|
|
/// Create declaration name location information for a base name.
|
|
explicit DeclNameLoc(SourceLoc baseNameLoc)
|
|
: DeclNameLoc(baseNameLoc.getOpaquePointerValue(), 0, false) {}
|
|
|
|
explicit DeclNameLoc(ASTContext &ctx, SourceLoc moduleSelectorLoc,
|
|
SourceLoc baseNameLoc)
|
|
: DeclNameLoc(ctx, moduleSelectorLoc, baseNameLoc,
|
|
SourceLoc(), {}, SourceLoc()) { }
|
|
|
|
/// Create declaration name location information for a compound
|
|
/// name.
|
|
DeclNameLoc(ASTContext &ctx, SourceLoc baseNameLoc,
|
|
SourceLoc lParenLoc,
|
|
ArrayRef<SourceLoc> argumentLabelLocs,
|
|
SourceLoc rParenLoc)
|
|
: DeclNameLoc(ctx, SourceLoc(), baseNameLoc,
|
|
lParenLoc, argumentLabelLocs, rParenLoc) { }
|
|
|
|
DeclNameLoc(ASTContext &ctx, SourceLoc moduleSelectorLoc,
|
|
SourceLoc baseNameLoc,
|
|
SourceLoc lParenLoc,
|
|
ArrayRef<SourceLoc> argumentLabelLocs,
|
|
SourceLoc rParenLoc);
|
|
|
|
/// Whether the location information is valid.
|
|
bool isValid() const { return getBaseNameLoc().isValid(); }
|
|
|
|
/// Whether the location information is invalid.
|
|
bool isInvalid() const { return getBaseNameLoc().isInvalid(); }
|
|
|
|
/// Whether this was written as a compound name.
|
|
bool isCompound() const { return NumArgumentLabels > 0; }
|
|
|
|
/// Retrieve the location of the base name.
|
|
SourceLoc getBaseNameLoc() const {
|
|
const SourceLoc *SourceLocs = getSourceLocs();
|
|
if (SourceLocs == nullptr)
|
|
return SourceLoc();
|
|
return SourceLocs[BaseNameIndex];
|
|
}
|
|
|
|
/// Retrieve the location of the left parentheses.
|
|
SourceLoc getLParenLoc() const {
|
|
if (NumArgumentLabels == 0) return SourceLoc();
|
|
return getSourceLocs()[LParenIndex];
|
|
}
|
|
|
|
/// Retrieve the location of the right parentheses.
|
|
SourceLoc getRParenLoc() const {
|
|
if (NumArgumentLabels == 0) return SourceLoc();
|
|
return getSourceLocs()[RParenIndex];
|
|
}
|
|
|
|
/// Retrieve the location of an argument label.
|
|
SourceLoc getArgumentLabelLoc(unsigned index) const {
|
|
if (index >= NumArgumentLabels)
|
|
return SourceLoc();
|
|
return getSourceLocs()[FirstArgumentLabelIndex + index];
|
|
}
|
|
|
|
SourceLoc getModuleSelectorLoc() const {
|
|
if (!HasModuleSelectorLoc) return SourceLoc();
|
|
return getSourceLocs()[ModuleSelectorIndex];
|
|
}
|
|
|
|
SourceLoc getStartLoc() const {
|
|
return HasModuleSelectorLoc ? getModuleSelectorLoc() : getBaseNameLoc();
|
|
}
|
|
|
|
SourceLoc getEndLoc() const {
|
|
return NumArgumentLabels == 0 ? getBaseNameLoc() : getRParenLoc();
|
|
}
|
|
|
|
/// Retrieve the complete source range for this declaration name.
|
|
SourceRange getSourceRange() const {
|
|
return SourceRange(getStartLoc(), getEndLoc());
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#endif // SWIFT_AST_DECL_NAME_LOC_H
|